Проблема была решена в комментариях без должного объяснения:
Окружающий скрипт с одинарными кавычками не работает? 's/$/;"newc"/'
да, это сработало!
Этот ответ поможет пролить свет на то, что произошло и почему решение работает.
В вашей оригинальной команде цитирование выглядит так:
sed "s/$/;"newc"/" file.csv
# ^ ^ a matching pair of quotes
# ^ ^ another pair of quotes
# s/$/; / these fragments are quoted
# newc this fragment is not quoted at all
Цитаты, которые вы использовали, потребляются оболочкой. Их присутствие указывает оболочке обрабатывать строки в кавычках несколько иначе, чем строки в кавычках, например, точка с запятой в кавычках (;
) не является разделителем команд; затем они исчезают, т.е. оболочка не передает их в sed
.
Обратите внимание, что newc
содержит специальных символов для оболочки, он ведет себя одинаково, независимо от того, указан он в кавычках или нет. Это означает, что newc
может быть заключен в кавычки, вот так:
sed "s/$/;""newc""/" file.csv
# ^ ^ added pair of quotes
Но это эквивалентно
sed "s/$/;newc/" file.csv
и после того, как оболочка потребит, кавычки sed
получат следующие аргументы: s/$/;newc/
, file.csv
. Как видите, инструмент вообще не получает кавычек.
Чтобы передать кавычки в sed
вам нужно сделать так, чтобы они "выживали" при разборе, выполняемом оболочкой. Есть несколько способов сделать это. Два общих подхода:
Спасаясь с \
. Внутри двойных кавычек вы можете экранировать символ двойной кавычки, поэтому он рассматривается как часть строки в кавычках, а не как заключительная кавычка. В твоем случае:
sed "s/$/;\"newc\"/" file.csv
Смешивание цитат. Двойная кавычка внутри одинарных кавычек остается. Упомянутое решение использует этот факт:
sed 's/$/;"newc"/' file.csv
Одинарная кавычка внутри двойных кавычек также остается. Например, если вам нужно передать буквальный аргумент '"
в echo
, это сработает:
echo "'"'"'
# ^ ^ # a pair of double quotes that make the single quote survive
# ^ ^ # a pair of single quotes that make the double quote survive
Иногда полезно вызвать set -x
перед командой "неправильного поведения", чтобы узнать, что осталось после того, как оболочка проанализирует его. Ваша оригинальная команда и две фиксированные генерируют это (вывод от sed
опущен для ясности):
$ sed "s/$/;"newc"/" file.csv # original command
+ sed s/$/;newc/ file.csv
$ # the above line contains what sed really got
$ sed "s/$/;\"newc\"/" file.csv # fixed
+ sed s/$/;"newc"/ file.csv
$ # this time sed got the right string
$ sed 's/$/;"newc"/' file.csv # also fixed
+ sed s/$/;"newc"/ file.csv
$ # again the right string
$
Примечание: в конце вызовите set +x
чтобы вернуться к тому, что сделал set -x
.