Как сопоставить несколько файлов в AWK? - PullRequest
0 голосов
/ 24 февраля 2019

Я пытаюсь сопоставить серию .csv файлов журнала, которые названы по дате (например, 2019-02-24.csv).Их много, поэтому я пытаюсь составить сценарий процесса.Я создал скрипт AWK, который объединяет отдельные файлы:

awk ' FNR==1 { while (/"_time",PIN,FULLNAME,OFFICE,Acronym,Name/) getline; } 1 { print } ' 2019-01-01.csv >> usage_history.csv

Но у меня не получается, когда я пытаюсь связать команды AWK вместе с циклом управления в BASH:

for i in {01..28}; do echo "awk ' FNR==1 { while (/\"_time\",PIN,FULLNAME,OFFCODE,Acronym,Name/) getline; } 1 { print } ' 2019-01-$i.csv >> user_history.csv"; done

Когда я запускаю это, он выводит правильные команды в командную строку, но сценарии awk не выполняются (они только печатаются).Если я запускаю его без echo, я получаю сообщения о том, что файл не существует;хотя все файлы присутствуют:

bash: awk ' FNR==1 { while (/"_time",PIN,FULLNAME,OFFCODE,Acronym,Name/) getline; } 1 { print } ' 2019-01-01.csv >> user_history.csv: No such file or directory

Чего мне не хватает в моем цикле?


Вот сокращенный пример команды и сообщений об ошибках:

$ for i in {01..02}; do "awk ' FNR==1 { while (/\"_time\",PIN,FULLNAME,OFFCODE,Acronym,Name/) getline; } 1 { print } ' 2019-01-$i.csv >> user_history.csv"; done
bash: awk ' FNR==1 { while (/"_time",PIN,FULLNAME,OFFCODE,Acronym,Name/) getline; } 1 { print } ' 2019-01-01.csv >> user_history.csv: No such file or directory
bash: awk ' FNR==1 { while (/"_time",PIN,FULLNAME,OFFCODE,Acronym,Name/) getline; } 1 { print } ' 2019-01-02.csv >> user_history.csv: No such file or directory

Ответы [ 3 ]

0 голосов
/ 24 февраля 2019

Не могли бы вы попробовать следующее.

awk '!/"_time",PIN,FULLNAME,OFFCODE,Acronym,Name/' 2019-01-[0-9]*.csv >> user_history.csv

Вот следующие пункты , почему можно использовать этот подход:

1-Использование цикла for и вызов команды awk в этом случае будет лишним.Мы должны использовать умный подход, когда awk может читать несколько файлов, тогда мы должны подать в суд на него.

2 - Теперь идет часть getline, которую вы пробовали в своем коде, поэтому, если мы хотим отрицать любую строку, тогдапросто отрицаем его, используя !/string_to_be_skipped/, поэтому он будет искать только те строки, которые НЕ имеют этой строки.

3 - При упоминании файла (нескольких файлов) в одной команде awk я использовал 2019-01-[0-9]*.csv почемупотому что, поскольку вы НЕ сказали, будут ли файлы создаваться ежедневно или нет, в случае, если мы зададим стиль цикла, а этот конкретный файл НЕ будет представлен, мы получим ошибку.Для примера, скажем, я использую следующую команду awk, где я намеренно удалил файл с именем (2019-01-02.csv).

awk '........' 2019-01-{01..29}.csv
awk: cannot open 2019-01-02.csv (No such file or directory)

Поэтому, чтобы избежать подобных ситуаций, я использовал 2019-01-[0-9]*.csv, где он будет искать толькофайлы, которые имеют цифры после 2019-01-0 и будут зацикливаться, НЕ запускаются в цикле и жалуются на отсутствие какого-либо файла xyz и т. д.

0 голосов
/ 24 февраля 2019

Спасибо @Tiw и @ RavinderSingh13 за руководство.Вот последний скрипт awk, который хорошо работает для моего случая, когда у меня есть ежедневные файлы за несколько дней, месяцев и лет (в данном случае только 2018 и 2019):

awk '! / "_time ", PIN, FULLNAME, OFFCODE, Сокращение, Имя / '201 [8-9] - [0-1] [0-2] - [0-3] [0-9] .csv >> user_history.csv

0 голосов
/ 24 февраля 2019

Попробуйте это:

for i in {01..28}; do awk '!/"_time",PIN,FULLNAME,OFFCODE,Acronym,Name/' 2019-01-$i.csv >>user_history.csv;done

Команды после do не должны заключаться в кавычки.
А то, что вы делали, по сути равнозначно игнорированию строк заголовка.
{print} после1 не требуется - один 1 подразумевает {print}.1 должен предоставить true.
- Когда есть только выражение, но нет блока, блок подразумевает {print}.
- И только регулярное выражение равно $0~/regex/, и здесьЯ отрицал это.

Если внутри цикла нет другой команды, вы можете упростить цикл с помощью одной команды awk:

awk '!/"_time",PIN,FULLNAME,OFFCODE,Acronym,Name/' 2019-01-{01..28}.csv >>user_history.csv

Но эта команда выдаст ошибку и прекратит выполнение, когдаодин из файлов не существовал.

Другой способ:

awk '!/"_time",PIN,FULLNAME,OFFCODE,Acronym,Name/' 2019-01-[0-3][0-9].csv >>user_history.csv

Этот будет соответствовать только именам файлов, а не циклу для них.
Он не прекратит выполнение и не выдаст ошибку, так что если файл отсутствуетты не узнаешьИ он будет соответствовать дополнительным файлам, если они существуют.
Например, он будет читать 2019-01-34.csv, если он существует.

Итак, если вы хотите, чтобы предупреждения (предупреждения не влияли на результаты), но не хотели останавливать команды, используйте первый цикл for.

Подводные камни:
[0-3][1-9] не будет соответствовать 10, 20 и 30, но будет совпадать с 32 до 39.
[0-9]* будет соответствовать любому большему числу, но с 20до 29 до 3 или аналогично, это строковый порядок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...