Удаление одиночных и двойных кавычек в строке с помощью команд bash/standard Linux

Я ищу что-то, что будет транслировать строку следующим образом, используя только bash/стандартные команды Linux:

  • Одиночные кавычки, окружающие строку, должны быть удалены
  • Двойные кавычки, окружающие строку, должны быть удалены
  • Некотируемые строки должны оставаться теми же
  • Строки с непревзойденными окружающими цитатами должны оставаться теми же
  • Одиночные кавычки, которые не окружают строку, должны оставаться
  • Двойные кавычки, которые не окружают строку, должны оставаться

Например:

  • "Пища" должна стать пищей
  • "Пища" должна стать пищей
  • Пища должна оставаться прежней
  • "Еда" должна оставаться прежней.
  • "Пища" должна оставаться прежней.
  • 'Fo'od' должен стать Fo'od
  • "Fo'od" должен стать Fo'od
  • Fo'od должен оставаться тем же
  • 'Fo "od' должен стать Fo" od
  • "Fo" od "должен стать Fo" od
  • Fo "od должен оставаться тем же

Спасибо!

+20
источник поделиться
7 ответов

Это должно сделать это:

sed "s/^\([\"']\)\(.*\)\1\$/\2/g" in.txt

Где in.txt:

"Fo'od'
'Food'
"Food"
"Fo"od'
Food
'Food"
"Food'
'Fo'od'
"Fo'od"
Fo'od
'Fo"od'
"Fo"od"
Fo"od

И expected.txt:

"Fo'od'
Food
Food
"Fo"od'
Food
'Food"
"Food'
Fo'od
Fo'od
Fo'od
Fo"od
Fo"od
Fo"od

Вы можете проверить, что они соответствуют:

diff -s <(sed "s/^\([\"']\)\(.*\)\1\$/\2/g" in.txt) expected.txt
+31
источник

Вы можете использовать tr:

echo "$string" | tr -d 'chars to delete' 

... также работает, однако, как известно, "tr" является проблематичным для гораздо более старых (около Redhat 9-иш) распределений. tr является аббревиатурой 'translate', обычно используемой в трубах для преобразования ввода. Опция -d просто означает "удалить".

Большинство современных версий также содержат предопределенные макросы, чтобы преобразовать верхние в нижние, нижние в верхние, убить пустое пространство и т.д. Следовательно, если вы его используете, возьмите секунду, чтобы высунуть то, что еще он делает (см. help output/man страница), пригодится.

+14
источник

Возможно, вы захотите использовать sed...

echo $mystring | sed -s "s/^\(\(\"\(.*\)\"\)\|\('\(.*\)'\)\)\$/\\3\\5/g"
+7
источник
VAR="'FOOD'"

VAR=$(eval echo $VAR)

Объяснение: Поскольку кавычки уже поняты оболочкой, вы можете попросить оболочку оценить команду, которая просто эхо-строки цитирует строку, так же, как это происходит при ее вводе.

Здесь eval echo $VAR расширяется до eval echo 'FOOD', потому что кавычки фактически являются частью значения VAR. Если вы запустили echo 'FOOD' в оболочку, вы получили бы FOOD (без кавычек). Что делает eval: он берет свой вход и запускает его как команду оболочки.

+6
источник

Просто используя встроенные функции Bash (т.е. расширение параметра Bash):

IFS=' ' 

food_strings=( "'Food'" '"Food"' Food "'Food\"" "\"Food'" "'Fo'od'" "\"Fo'od\"" "Fo'od" "'Fo\"od'" '"Fo"od"' 'Fo"od'  )  

for food in ${food_strings[@]}; do 

   [[ "${food#\'}" != "$food" ]] && [[ "${food%\'}" != "$food" ]] && { food="${food#\'}"; food="${food%\'}"; } 

   [[ "${food#\"}" != "$food" ]] && [[ "${food%\"}" != "$food" ]] && { food="${food#\"}"; food="${food%\"}"; } 

   echo "$food"

done 

Для еще одного примера расширения параметра Bash см. ниже:

http://codesnippets.joyent.com/posts/show/1816

+4
источник

Просто наткнулся на это. Для первых трех тестовых случаев eval echo $string работает хорошо. Чтобы заставить его работать во всех запрошенных случаях и некоторых других, я придумал это (проверено с помощью bash и dash):

#!/bin/sh

stripquotes() {
    local firstchar="`substr "$1" 0 1`"
    local len=${#1}
    local ilast=$((${#1} - 1))
    local lastchar="`substr "$1" $(($len - 1))`"
    if [ "$firstchar" = '"' ] || [ "$firstchar" = "'" ] && [ $firstchar = $lastchar ]; then
        echo "`substr "$1" 1 $(($len - 2))`"
    else
        echo "$1"
    fi
}

# $1 = String.
# $2 = Start index.
# $3 = Length (optional). If unspecified or an empty string, the length of the
#      rest of the string is used.
substr() {
    local "len=$3"
    [ "$len" = '' ] && len=${#1}
    if ! (echo ${1:$2:$len}) 2>/dev/null; then
        echo "$1" | awk "{ print(substr(\$0, $(($2 + 1)), $len)) }"
    fi
}

var="'Food'"
stripquotes "$var"

var='"Food"'
stripquotes "$var"

var=Food
stripquotes "$var"

var=\'Food\"
stripquotes "$var"

var=\"Food\'
stripquotes "$var"

var="'Fo'od'"
stripquotes "$var"

var="\"Fo'od\""
stripquotes "$var"

var="Fo'od"
stripquotes "$var"

var="'Fo\"od'"
stripquotes "$var"

var="\"Fo\"od\""
stripquotes "$var"

var="Fo\"od"
stripquotes "$var"

# A string with whitespace should work too.
var="'F\"o 'o o o' o\"d'"
stripquotes "$var"

# Strings that start and end with the same character that isn't a quote or
# doublequote should stay the same.
var="TEST"
stripquotes "$var"

# An empty string should not cause errors.
var=
stripquotes "$var"

# Strings of length 2 that begin and end with a quote or doublequote should not
# cause errors.
var="''"
stripquotes "$var"
var='""'
stripquotes "$var"
+2
источник
python -c "import sys;a=sys.stdin.read();a=a.strip();print (a[1:-1] if a[0]==a[-1] and a[0] in \"'\\\"\" else a)"

он не справляется с крайними случаями очень хорошо (например, пустая строка), но он будет служить отправной точкой. Он работает, разбивая передний и задний символы, если они одинаковы, и если они "или"

+1
источник

Посмотрите другие вопросы по меткам или Задайте вопрос