2016-07-04 3 views
4

Всегда ли после изменения определенного поля в awk информация о разделителе полей вывода теряется? Что произойдет, если есть несколько разделителей полей, и я хочу, чтобы они были восстановлены?Выходные разделители полей в awk после подстановки в полях

Например, предположим, что у меня есть простой файл example, который содержит:

a:e:i:o:u 

Если я просто запустить awk скрипт, который принимает во внимание разделителем поля ввода, который печатает каждую строку в мой файл, например as running

awk -F: '{print $0}' example 

Я увижу оригинальную линию. Если, однако, я изменяю одно из полей напрямую, например. с

awk -F: '{$2=$2"!"; print $0}' example 

Я не вернусь модифицированной версией оригинальной линии, а я вижу поле, разделенное сепаратор пробелов по умолчанию, то есть:

a e! i o u 

я могу получить обратно модифицированную версию оригинала, задающий OFS, например:

awk -F: 'BEGIN {OFS=":"} {$2=$2"!"; print $0}' example 

в случае, однако, где существует несколько потенциальных разделители поля, но в случае нескольких сепараторов есть простой способ восстановления исходных сепараторов?

Например, если example было как : и ; как разделители, я не мог использовать -F":|;" обработать файл, но OFS бы не быть достаточно, чтобы восстановить исходные сепараторы в их взаимном расположении.

Более точно, если мы перешли на example2, содержащего

a:e;i:o;u 

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

awk -F":|;" 'BEGIN {OFS=":"} {$2=$2"!"; print $0}' example2 

(или -F"[:;]"), чтобы получить

a:e!:i:o:u 

, но мы потеряли различие между и ; который был бы сохранить, если мы могли бы восстановить

a:e!;i:o;u 
+1

Вопрос один из редких хороших здесь. Почему бы просто не добавить нерабочий пример, используя '-F '[:;]''. Это сделало бы вопрос идеальным - imo – hek2mgl

+1

Явный пример добавлен – borrible

+0

Обозначение разделителя полей RT будет очевидным расширением GNU. Интересно, почему у них этого нет. –

ответ

3

Вы должны использовать GNU AWK для 4-арг расколоть(), который сохраняет разделители, как RT делает для RS:

$ awk -F'[:;]' '{split($0,f,FS,s); $2=$2"!"; r=s[0]; for (i=1;i<=NF;i++) r=r $i s[i]; $0=r} 1' file 
a:e!;i:o;u 

Eсть нет автоматически заполненного массива строк соответствия FS из-за того, насколько дорого будет время и память для хранения строки, которая соответствует FS каждый раз, когда вы разделяете запись на поля. Вместо этого пользователи GNU awk предоставили 4-й аргумент для разделения(), чтобы вы могли сделать это сами, если/когда захотите. Это результат долгого разговора несколько лет назад в группе новостей comp.lang.awk между опытными пользователями awk и поставщиками gawk, прежде чем все согласны с тем, что это лучший подход.

См. split() по адресу https://www.gnu.org/software/gawk/manual/gawk.html#String-Functions.

Смежные вопросы