Удаление одинарных и двойных кавычек в строке только с использованием bash/стандартных команд Linux
Вопрос
Я ищу что-то, что будет переводить строку следующим образом, используя только команды bash/стандартные Linux:
- Одинарные кавычки вокруг строки следует удалить.
- Двойные кавычки вокруг строки должны быть удалены.
- Строки без кавычек должны оставаться прежними
- Строки с несовпадающими окружающими кавычками должны оставаться прежними.
- Одинарные кавычки, не заключающие строку, должны оставаться
- Двойные кавычки, не заключающие строку, должны оставаться
Например:
- «Еда» должна стать едой
- «Еда» должна стать Едой
- Еда должна оставаться прежней
- «Еда» должна остаться прежней
- «Еда» должна остаться прежней
- «Фод» должен стать Фодом
- «Фод» должен стать Фодом
- Еда должна оставаться прежней
- «Фоод» должен стать Фоодом
- «Фоод» должен стать Фоодом
- Еда должна оставаться прежней
Спасибо!
Решение
Это должно сделать это:
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 см.:
Тоже только что наткнулся на это.Для первых трех тестовых случаев 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)"
он не очень хорошо обрабатывает крайние случаи (например, пустую строку), но послужит отправной точкой.Он работает путем разделения переднего и заднего символов, если они одинаковы и если они ' или "