Взаимодействие bash с awk:

Я новичок в awk и искал возможность настроить какой-то сценарий bash на работе, который взаимодействует с утилитой awk для анализа вывода некоторых системных файлов. Я внес свои изменения, основываясь на своем понимании, а затем возобладал здравый смысл, и поэтому я подумал, что напишу простую тестовую программу, чтобы опробовать тот же логический шаблон. Но, к моему разочарованию, тестовая программа не сработала должным образом. Я воспроизвожу ниже сценарий bash и сценарий утилиты awk, который я закодировал, вместе с ошибкой, которую я получаю. Цените свои мысли.

bash script
-----------

#!/bin/bash

string=$'a\nb\nc\nd\ne'
echo "$string"

awk -v input=${string} -f post.awk < file_input.txt > file_output.txt


awk script
----------

#!/bin/gawk

BEGIN {
  
  getline tmp
  print tmp > $3

}

END{

 print $1 > $3

}

В сценарии awk я пытаюсь прочитать одну строку "Only one line" внутри file_input.txt и записать ее в file_output.txt внутри блока BEGIN. Внутри блока END я пытаюсь записать строку, переданную в командной строке скрипту awk, в file_output.txt.

Я получаю следующий вывод при запуске скрипта bash:

а

б

с

г

awk: cmd. line:1: fatal: cannot open file 'c' for reading (No such file or directory)

Очевидно, я не понимаю, как awk обрабатывает аргументы командной строки на основе ошибки. Я предполагал, что в строке

awk -v input=${string} -f post.awk < file_input.txt > file_output.txt

$1 would be input
$2 would be file_input.txt
$3 would be file_output.txt

Может ли кто-нибудь указать, где я ошибся в своих предположениях?

ТИА

Можете ли вы опубликовать точный набор входных данных для вашего сценария bash и сценария awk, а также точный ожидаемый желаемый результат. На данный момент неясно

Inian 10.07.2023 09:45

В Awk $1, $2 не относятся к аргументам командной строки. Почитайте об этом. Во-вторых, перенаправления в любом случае не являются аргументами команды! Если вы вызываете сценарий оболочки или функцию, такую ​​как command < file1 > file2, не будет $1 и $2, удерживающих file1 и file2. Вместо этого стандартный ввод перенаправляется с file1, а стандартный вывод перенаправляется на file2. У command нет аргументов. Но в любом случае помните, что $1 и $2 в Awk не относятся к аргументам. В Awk есть ARGC счетчик и ARGV[] ассоциативный массив для доступа к командной строке.

Kaz 10.07.2023 11:35

В awk$1 — это содержимое первого поля текущей строки.

user1934428 10.07.2023 14:02

пожалуйста, обновите вопрос с (правильным) ожидаемым результатом

markp-fuso 10.07.2023 14:54

Вам не нужны отдельные блоки BEGIN и END, и вы не должны использовать getline для этого , весь скрипт должен быть {print; exit} END{print input} или {print; print input; exit} или подобным, в зависимости от ваших неустановленных требований для обработки пустого файла. отредактируйте свой вопрос, чтобы показать ожидаемый результат, когда входной файл пуст, чтобы мы могли вам помочь.

Ed Morton 10.07.2023 16:33

Как указывает тег bash , который вы использовали: «Скрипты оболочки с синтаксисом или другими ошибками, пожалуйста, проверьте их на shellcheck.net, прежде чем публиковать их здесь». Этот инструмент укажет на некоторые проблемы вашего скрипта.

Ed Morton 10.07.2023 16:34
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

В вашем коде много ошибок:

  1. Вы забываете поставить кавычки ${string}, что приводит к запутанному поведению, когда awk хочет прочитать файл c. Из-за неправильного цитирования вы фактически пытаетесь выполнить:

    $ awk -v input=a b c d -f post.awk < file_input.txt > file_output.txt
    

    Здесь вы устанавливаете переменную input=a и пытаетесь прочитать 3 файла (b, c и d). Файл file_input.txt не влияет на скрипт awk, если только вы активно не обрабатываете /dev/stdin в post.awk.

  2. Вы делаете ошибку и считаете, что $n в коде awk представляет _n_th аргумент, переданный awk. Это неправда. В awk $n представляет n_th поле текущей входной записи.

  3. В блоке BEGIN не определена входная запись $0. Только когда определена входная запись, определяются поля ($i, i>0). С другой стороны, блок END знает последнюю входную запись, прочитанную из входного файла.

Вы можете определить входную запись в блоке BEGIN, используя getline как есть, но не getline var, поскольку это не определяет $0.

Итак, как мы можем заставить это работать сейчас.

Если вы просто полагаетесь на простой bash, он будет работать так, как вы хотите. То есть пусть bash определяет с помощью перенаправления, что такое /dev/stdin и /dev/stdout используемой команды. Пример:

$ binary < f1 > f2

Здесь исполняемый файл binary выполняется, когда /dev/stdin указывает на f1, а /dev/stdout указывает на f2.

Таким образом, вы можете сделать то же самое и написать свою программу awk, чтобы просто принять значения по умолчанию /dev/stdin и /dev/stdout.

# post.awk
BEGIN { getline tmp; print tmp }
END   { print input }

и выполняя это как:

$ awk -v input = "${string}" -f post.awk file_input.txt > file_output.txt

должен сделать трюк.

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