У меня есть CSV, в хвосте которого отсутствуют данные столбца, например. следующее:
Data1,Data2,User
abc,def,foo
hij,klm,foo
nop,qrs
tuv,wxy
В этом случае я хочу добавить bar в конец строк без foo. Это легко сделать с помощью sed '/foo/!s/$/,bar/'. Проблема в том, что это также добавит ,bar в первую строку. Я знаю, что могу пропустить первую строку с помощью 2,$, но когда я это делаю, кажется, что не соблюдаются инструкции «номер строки» и «отрицаемый поиск». Есть ли способ внутри sed объединить оба?
(Для ясности: я знаю, что у меня есть другие варианты. Я, вероятно, могу выполнить несколько операций sed или написать простой макрос в vim и тоже сделать это за секунду. Но в данном случае я хочу посмотреть, сможет ли это сделать. быть выполнено полностью за один сеанс.)





Это может сработать для вас (GNU sed):
sed '1!{/foo/!s/$/,bar/}' file
Если это не первая строка и строка не содержит foo, добавьте ,bar.
Альтернатива:
sed '1b;/foo/b;s/$/,bar/' file
Однако в результате появится вторая строка abc,def,foo,bar, а это не то, чего я хочу.
упс неправильно прочитал вопрос
Вот команда sed, которая должна работать с любой версией sed:
sed '2,${ /foo/!s/$/,bar/; }' file
Data1,Data2,User
abc,def,foo
hij,klm,foo
nop,qrs,bar
tuv,wxy,bar
Если вы хотите дать awk шанс, то это гораздо проще сделать с любой версией awk:
awk 'NR > 1 && !/foo/ {$0 = $0 ",bar"} 1' file
Data1,Data2,User
abc,def,foo
hij,klm,foo
nop,qrs,bar
tuv,wxy,bar
sed отлично подходит для выполнения s/old/new в отдельных строках, но для всего остального просто используйте awk. Использование любого awk в любой оболочке на каждом компьютере Unix:
$ awk -F, 'NR==1{n=NF} NF<n{$0=$0 ",bar"} 1' file
Data1,Data2,User
abc,def,foo
hij,klm,foo
nop,qrs,bar
tuv,wxy,bar
При этом вам не нужно указывать foo или что-то еще, что могло бы тесно связать ваш код с вашими данными. Скрипт сохраняет в переменной (n=NF) количество полей (NF) в первой строке заголовка входных данных (NR==1), и если он встречает какую-либо строку с меньшим количеством полей, чем это количество полей (NF<n), то он добавляет ,bar в конец. . Затем он печатает каждую строку (1 — идиоматическое сокращение {print}).
Возможно
sed '1b;/foo/!s/$/,bar/' file? Это приведет к прекращению любой обработки первой строки.