- РЕДАКТИРОВАТЬ 2019-Oct-11 - Простой пример
Я хочу, чтобы awk
повторно считал TAB
символ, встроенный в $0
в качестве содержимого, когда он обрабатывает входную запись $0
после изменения значения поля ($1
, $2
, ..).
Вот краткий пример. Например, в выводе ниже «t @ 48
» означает, что в позиции 48 записи данных $0
имеется TAB
. Обратите внимание, что «\t
» расширен до: TAB
chr (9) в качестве начальной обработки ввода (помечено raw ).
Пример вывода :
$ ./tmp.awk tmp.input
raw $0: ' line with spaces here a tab between AAA\tBBB', t @ 0, NF = 8, len = 52.
$1: 'line', len = 4.
unescape $0: ' line with spaces here a tab between AAA BBB', t @ 48, NF = 9, len = 51.
$1 = $1, $0: 'line with spaces here a tab between AAA BBB', t @ 0, NF = 9, len = 43.
unescape $0: ' line with spaces here a tab between AAA BBB', t @ 48, NF = 9, len = 51.
$1 = "", $0: ' with spaces here a tab between AAA BBB', t @ 0, NF = 9, len = 39.
final $0: ' with spaces here a tab between AAA BBB', t @ 0, NF = 9, len = 39.
Когда "\t
" расширен и $ 0 обновлен, awk
правильно перестраивает и дает 9 полей (больше 8). ( тик )
Входная запись :
line with spaces here a tab between AAA\tBBB
Желаемый Результат :
Конечная цель состоит в том, чтобы иметь возможность удалить содержимое поля $ 1, сохранив при этом все форматирование и интервал будет , как показано.
$0: ' with spaces here a tab between AAA BBB', t @ 44, NF = 8, len = 47.
С удалением только указанных $1
-символов, что является "линией". Включая TAB между "AAA" и "BBB". Я показал на одно поле меньше (NF = 8). Сам Awk, похоже, сохраняет пустую ячейку $1
, поэтому NF = 9
также будет приемлемым.
После строки, помеченной: $1 = $1'
, когда мы изменяем значение $1
2 .
{
:
print " unescape $0: '" $0 "', t @ " index( $0, "\t" ) ", NF = " NF ", len = " length( $0 ) ".";
$1 = $1; # force record to be reconstituted
print " $1 = $1, $0: '" $0 "', t @ " index( $0, "\t" ) ", NF = " NF ", len = " length( $0 ) ".";
}
output ...
unescape $0: ' line with spaces here a tab between AAA BBB', t @ 48, NF = 9, len = 51.
$1 = $1, $0: 'line with spaces here a tab between AAA BBB', t @ 0, NF = 9, len = 43.
Обратите внимание, что пока у меня еще есть 7 полей в этой строке. НЕТ ДЛИННОГО TAB
символа, и после пробела «здесь» были удалены пробелы. Эти изменения форматирования нежелательны для этого варианта использования.
Я получаю этот результат согласованно НЕТ, какие бы значения я ни вводил для разделителя полей, FS
(даже перевод строки) и OFS
. На самом деле изменение OFS ухудшает ситуацию.
Поведение не ожидалось. Однако после некоторых комментариев вполне возможно, что это предписано, несмотря ни на что.
Образец awk
скрипт:
{
print "";
print "raw $0: '" $0 "', t @ " index( $0, "\t" ) ", NF = " NF ", len = " length( $0 ) ".";
print "$1: '" $1 "', len = " length( $1 ) ".";
gsub(/\\t/, "\t", $0); # expand any embedded TAB-s
print "unescape $0: '" $0 "', t @ " index( $0, "\t" ) ", NF = " NF ", len = " length( $0 ) ".";
preserve = $0;
print "";
$1 = $1; # force record to be reconstituted
print "$1 = $1, $0: '" $0 "', t @ " index( $0, "\t" ) ", NF = " NF ", len = " length( $0 ) ".";
print "";
$0 = preserve;
print "unescape $0: '" $0 "', t @ " index( $0, "\t" ) ", NF = " NF ", len = " length( $0 ) ".";
$1 = "";
print "$1 = \"\", $0: '" $0 "', t @ " index( $0, "\t" ) ", NF = " NF ", len = " length( $0 ) ".";
print "";
print "final $0: '" $0 "', t @ " index( $0, "\t" ) ", NF = " NF ", len = " length( $0 ) ".";
print "";
}
Вопросы ...
- Как я могу получить желаемое поведение? Смысл, нет редактирования записи при удалении поля?
- Если это невозможно - существует ли метод, который сохраняет целостность и интервал «текущей» записи $ 0?
- Например, я искал массив, который отображает все поляк записи $ 0, но не нашел ее.
- Как можно сохранить
TAB
в примере. - Можно ли предотвратить редактирование записи
$0
?
Символы были удалены. Изучение показывает, что awk
отредактировал повторные пробелы (удалил их) и TAB.
Единственный пробел не является виновником, он, по-видимому, является восстановлением или изготовлением записи за 0 долларов.
Ссылка :
Области из UG ... Руководство пользователя Gnu Awk :
Поля заполненыобычно разделяются пробелами (пробелами, табуляцией и символами новой строки), а не одиночными пробелами. Два пробела подряд не разделяют пустое поле. Значением по умолчанию разделителя полей FS является строка, содержащая один пробел "".
Я понял, что пространство FS особенное. Однако даже когда я ставлю странную FS, такую как "W" и "\ n", символы все равно удаляются из $0
после шага перестройки $1 = $1
.
- Вывод FS не используется при повторной обработке
$0
Изменение значения $0 = new string
сработало, как и ожидалось. Количество полей увеличивается, потому что awk
распознает символ табуляции. Я должен указать, что awk
в этом случае не удалял вкладку (как хотелось бы).
Изменение полей (Gnu Awk UG) :
Наконец, бывают случаи, когда удобно заставить awk восстановить всю запись, используя текущуюЗначения полей и ОФС. Для этого используйте, казалось бы, безобидное задание:
$1 = $1 # force record to be reconstituted
print $0 # or whatever else with $0
Это заставляет awk восстановить запись. Это помогает добавить комментарий, как мы показали здесь.
Используемая версия:
gawk -VGNU Awk 4.2.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.1.2)Copyright (C) 1989, 1991-2018 Free Software Foundation
Ubuntu 19.04
Эта инструкция не предупреждает, что в $0
может быть удалено 9 символов, или даже намекает, что это повлияет на $ 0.
Другоенеобъяснимые аспекты:
- У меня есть объяснение этому?
- Это только
gawk
или распространено среди альтернативных awk
-s?
Лично меня очень порадовало $0
не меняется. Много раз, когда я хочу awk
за его способность структурировать данные и сохранять неструктурированный источник для вывода.
Жду ваших мыслей.