У меня есть 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
? Это приведет к прекращению любой обработки первой строки.