Сопоставление шаблона и извлечение

У меня есть файл журнала, который выглядит следующим образом. Он показывает, что многие файлы отсутствуют. Я хотел бы перечислить это.

$cat datafile.txt
    /data/kay/20091012.csv
    gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091013.txt FNR=1) fatal: file not file
    /data/kay/20091014.csv
    gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091015.txt FNR=1) fatal: file not file
    gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091016.txt FNR=1) fatal: file not file
    /data/kay/20091017.csv
    gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091018.txt FNR=1) fatal: file not file

Я хотел бы указать даты, когда файл отсутствует. Мой скрипт ниже:

$script.sh
awk '{if ($1 -eq "gawk")print $4}' datafile.txt
echo ${echo $(awk '{if ($1 -eq "gawk")print $4}' datafile.txt):-14,8}

Он показывает ошибку. «Плохая замена»

Выход моего желания:

$outfile.txt
20091013
20091015
20091016
20091018

"Показывает ошибку": какая ошибка?

Renaud Pacalet 12.07.2023 09:56

Пожалуйста, отредактируйте свой вопрос и добавьте полное и точное сообщение об ошибке.

Renaud Pacalet 12.07.2023 10:01

Ваше использование echo, подстановки команд и расширения параметров совершенно неправильно. Во-первых, вам вообще не нужно echo. awk по умолчанию уже отправляет свой вывод на стандартный вывод. Повторять это совершенно бесполезно. Во-вторых, вы пытаетесь применить расширение параметра (точнее, расширение подстроки ${parameter:offset:length}) для подстановки команд; это не работает. Вы можете использовать расширение подстроки только для параметров (переменных bash, если хотите). И последнее, но не менее важное: вы накапливаете команды, в то время как awk или sed вполне способны делать то, что вы хотите, в одиночку. Читать их инструкции, может быть?

Renaud Pacalet 12.07.2023 10:14

Я понимаю. Большое спасибо @RenaudPacalet за объяснение ошибки. Я ценю это.

Kay 12.07.2023 10:16
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
51
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Использование sed

$ sed -En '/^ +gawk/s/[^)]*_([^.]*).*/\1/woutput.txt' input_file
$ cat output.txt
20091013
20091015
20091016
20091018

Использование awk

$ awk -F"[_.]" '/gawk/{print $3 > "output.txt" }' input_file
$ cat output.txt
20091013
20091015
20091016
20091018

Использование grep:

grep -oE '[0-9]{4}[0-9]{1,2}[0-9]{1,2}' input_file

С GNU grep с показанными вами образцами попробуйте следующее решение. Использование регулярного выражения и концепции ленивого сопоставления в регулярном выражении grep.

grep -oP '^[[:space:]]+gawk:.*?out/[0-9]+_\K(.*?)(\.txt)'  Input_file

Пусть datafile.txt контент будет

/data/kay/20091012.csv
gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091013.txt FNR=1) fatal: file not file
/data/kay/20091014.csv
gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091015.txt FNR=1) fatal: file not file
gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091016.txt FNR=1) fatal: file not file
/data/kay/20091017.csv
gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091018.txt FNR=1) fatal: file not file

При выполнении

awk '{if ($1 -eq "gawk")print $4}' datafile.txt

вы поручили своему awk вывести eq из 1-го поля, а затем соединить его с gawk, поскольку все эти поля не являются числами, а eq не было установлено 0, поэтому для каждой строки, которая оценивается как

0gawk

это считается правдивым в логическом контексте, поэтому будет print 4-е поле для каждой строки (пустая строка, если такого поля нет).

Вы должны использовать ==, если вам нужно сравнение, и примите во внимание, что вы ищете строки, где 1-е поле равно gawk:, после исправления ваш код становится

awk '{if ($1= = "gawk:")print $4}' datafile.txt

и дает вывод

(FILENAME=/data/kay/out/501_20091013.txt
(FILENAME=/data/kay/out/501_20091015.txt
(FILENAME=/data/kay/out/501_20091016.txt
(FILENAME=/data/kay/out/501_20091018.txt

Однако if здесь не требуется, так как GNU AWK использует пары шаблон-действие, поэтому приведенное выше может быть выражено как

awk '$1= = "gawk:"{print $4}' datafile.txt

Теперь вам нужно очистить вывод, я предлагаю следующую эвристику: сохранить одну или несколько цифр после _ и перед ., что может быть реализовано с помощью функции gensub следующим образом.

awk '$1= = "gawk:"{print gensub(/.*_([[:digit:]]+)[.].*/, "\\1", 1, $4)}' datafile.txt

который дает

20091013
20091015
20091016
20091018

Обратите внимание, что [.] обозначает буквальную точку, а . вне квадратных скобок обозначает любой символ.

(проверено в GNU Awk 5.1.0)

голые кости EREregex достаточно :

echo '
    /data/kay/20091012.csv
    gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091013.txt FNR=1) fatal: file not file
    /data/kay/20091014.csv
    gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091015.txt FNR=1) fatal: file not file
    gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091016.txt FNR=1) fatal: file not file
    /data/kay/20091017.csv
    gawk: cmd. line:4: (FILENAME=/data/kay/out/501_20091018.txt FNR=1) fatal: file not file' | 

mawk 'NF *= 2 < NF' OFS= FS='^[ \t]+gawk:[^_]+_|[.].+fatal.+$'

20091013
20091015
20091016
20091018

чтобы еще больше уменьшить regex до абсолютного минимума:


gawk 'NF *= 2 < NF' OFS= FS='^.+gawk:.+_|[.].+$'

и ДЕЙСТВИТЕЛЬНО ДЕЙСТВИТЕЛЬНО неуместный способ извлечения этого числа:

nawk '$+_ = +$2' FS='_' 
mawk '$0  = +$2' FS='_' 
gawk '$_  = +$2' FS='_'     

20091013
20091015
20091016
20091018

Другие вопросы по теме