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

StackOverflow https://stackoverflow.com/questions/758031

  •  09-09-2019
  •  | 
  •  

Вопрос

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

  1. Одинарные кавычки вокруг строки следует удалить.
  2. Двойные кавычки вокруг строки должны быть удалены.
  3. Строки без кавычек должны оставаться прежними
  4. Строки с несовпадающими окружающими кавычками должны оставаться прежними.
  5. Одинарные кавычки, не заключающие строку, должны оставаться
  6. Двойные кавычки, не заключающие строку, должны оставаться

Например:

  • «Еда» должна стать едой
  • «Еда» должна стать Едой
  • Еда должна оставаться прежней
  • «Еда» должна остаться прежней
  • «Еда» должна остаться прежней
  • «Фод» должен стать Фодом
  • «Фод» должен стать Фодом
  • Еда должна оставаться прежней
  • «Фоод» должен стать Фоодом
  • «Фоод» должен стать Фоодом
  • Еда должна оставаться прежней

Спасибо!

Это было полезно?

Решение

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

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

Где в.txt находится:

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

И ожидаемый.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

Другие советы

Вы могли бы использовать tr:

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

...также работает, однако известно, что использование «tr» проблематично в гораздо более старых (около Redhat 9-й версии) дистрибутивах. tr — это аббревиатура от «перевести», обычно используемая в каналах для преобразования входных данных.А -d опция просто означает «удалить».

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

VAR="'FOOD'"

VAR=$(eval echo $VAR)

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

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

⚠ИНЖЕКЦИЯ КОДА!

eval подвергать сценарии внедрению кода.

VAR=';ls -l'

VAR=$(eval echo $VAR)

вызовет выполнение ls -l.

Здесь можно было бы внедрить гораздо более вредоносные коды.

Вы, вероятно, захотите использовать СЭД...

echo $mystring | sed -s "s/^\(\(\"\(.*\)\"\)\|\('\(.*\)'\)\)\$/\\3\\5/g"

Просто используя встроенные функции 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

Тоже только что наткнулся на это.Для первых трех тестовых случаев 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"
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)"

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top