У меня есть файл журнала, который выглядит следующим образом. Он показывает, что многие файлы отсутствуют. Я хотел бы перечислить это.
$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
Пожалуйста, отредактируйте свой вопрос и добавьте полное и точное сообщение об ошибке.
Ваше использование echo, подстановки команд и расширения параметров совершенно неправильно. Во-первых, вам вообще не нужно echo. awk по умолчанию уже отправляет свой вывод на стандартный вывод. Повторять это совершенно бесполезно. Во-вторых, вы пытаетесь применить расширение параметра (точнее, расширение подстроки ${parameter:offset:length}) для подстановки команд; это не работает. Вы можете использовать расширение подстроки только для параметров (переменных bash, если хотите). И последнее, но не менее важное: вы накапливаете команды, в то время как awk или sed вполне способны делать то, что вы хотите, в одиночку. Читать их инструкции, может быть?
Я понимаю. Большое спасибо @RenaudPacalet за объяснение ошибки. Я ценю это.





Использование 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
"Показывает ошибку": какая ошибка?