передача параметров оболочки в awk не работает - PullRequest
4 голосов
/ 17 июня 2011

Почему это работает

for myfile in `find . -name "R*VER" -mtime +1`
do
   SHELLVAR=`grep ^err $myfile || echo "No error"`
   ECHO $SHELLVAR
done

и выводит

No error
err ->BIST Login Fail 3922 err 
No error
err ->IR Remote Key 1 3310 err 

Но это не

for myfile in `find . -name "R*VER" -mtime +1`
do
   SHELLVAR=`grep ^err $myfile || echo "No error"`
   awk -v awkvar=${SHELLVAR} '{print awkvar}'
done

и выводится

awk: cmd. line:1: fatal: cannot open file `{print awkvar}' for reading (No such file or directory)

Чего мне не хватает?

Ответы [ 4 ]

5 голосов
/ 17 июня 2011

Содержит ли $SHELLVAR пробел?Если это так, ваш сценарий awk неправильно обрабатывается, и предполагается, что {print awkvar} является именем файла, а не самой программой AWK.

У вас также есть проблема, когда оба значения для loop и программа awk оба портят STDIN.Фактически, ваш цикл for будет выполняться только один раз, поскольку AWK будет считывать все STDIN до тех пор, пока он не завершится.В конце концов, вы будете получать одну и ту же строку снова и снова, а затем ваша программа перестанет работать, так как awk ожидает большего количества STDIN.

Я думаю, вы хотите сделать что-то подобное ...

find . -name "R*VER" -mtime +1 | while read myfile
do
    echo "$SHELLVAR" | awk '{print $0}'
done

Таким образом, ваша команда echo поступает в ваш awk, что предотвращает чтение awk из оператора find.

В целом, вам лучше сделать следующее:

find . -name "R*VER" -mtime +1 | while read myfile
do
   ...
done

Вместо этого:

for myfile in `find . -name "R*VER" -mtime +1`
do
   ...
done

Это по нескольким причинам:

  1. Буфер командной строки может переполниться, и вы потеряетеимена файлов, но вы никогда не увидите ошибку.

  2. Команда поиска во втором примере должна сначала завершиться, прежде чем цикл for сможет начать выполняться.В первом примере поиск находит в цикле while.


ADDENDUM

Теперь, когда я увидел just-my-correct-мнения *Ответ 1039 *, я понимаю, что вы действительно сделали неправильно: вы забыли имя файла в команде awk:

find . -name "R*VER" -mtime +1 | while read myfile
do
   SHELLVAR=`grep ^err $myfile || echo "No error"`
   awk -v awkvar=${SHELLVAR} '{print awkvar}' $myfile
done

Теперь вопрос в том, что именно вы делаете с awk.Вы не печатаете ничего, кроме значения $SHELVAR для каждой строки в файле.Это, вероятно, не то, что вы хотите сделать.На самом деле, почему бы просто не сделать это:

find . -name "R*VER" -mtime +1 | while read myfile
do
   SHELLVAR=$(grep -q "^err" $myfile")
   if [ "x$SHELLVAR" != "x" ]
   then
      echo "$SHELLVAR"
   fi
done

Таким образом, вы распечатаете $SHELLVAR, но только если $SHELLVAR пусто.

Или вы можете использовать awk длявыведите только те строки, которые соответствуют вашему регулярному выражению:

find . -name "R*VER" -mtime +1 | while read myfile
do
   awk '/^err/ {print $0}' $myfile
done
4 голосов
/ 17 июня 2011

То, что вы пытаетесь сделать, возможно, но ... немного странно. Вот альтернатива для вас:

for f in $(find . -name "R*VER" -mtime +1)
do
    echo "$f"
    awk 'BEGIN{ec=0} /^err/{ec+=1;print} END{if(ec==0){print "No error"}}' "$f"
done

Таким образом, вам не нужно беспокоиться о grep, не нужно беспокоиться о переменных оболочки и вы можете хранить свою логику в одном месте на одном языке.

Обратите внимание, что этот код тестируется только частично, поскольку у меня нет ваших файлов данных, но тестирование у меня прошло нормально.

Если хотите, вы можете пойти еще дальше и написать все это в awk. В конце концов, это полноценный язык программирования общего назначения (с IMO, намного более чистый синтаксис, чем bash). Таким образом, вы полностью избавитесь от необходимости find, grep и bash. Однако я не буду писать этот сценарий. Вам придется взять справочную страницу awk и самостоятельно прочитать файл ввода / вывода.

4 голосов
/ 17 июня 2011

Вам нужно заключить в кавычки $SHELLVAR, чтобы не допустить разбиения оболочки.

awk -v awkvar="${SHELLVAR}" '{print awkvar}'
1 голос
/ 19 июня 2011

У вас уже есть альтернативные решения.Независимо от этого, я просто хочу ответить на ваш вопрос, то есть то, что вам не хватает:

awk -v awkvar=${SHELLVAR} '{print awkvar}'

Здесь awk пытается прочитать входные данные из STDIN,И это проблема. Awk пытается прочитать входные данные из STDIN, если вы не укажете входные файлы.Указанные команды для awk выполняются для каждого RECORD на входе (и по умолчанию запись является строкой).См. man awk, чтобы узнать больше о awk.

Но вот хак, если вы хотите, чтобы он продолжался без ввода:

awk -v awkvar=${SHELLVAR} 'BEGIN{print awkvar}'

BEGIN блоквыполняется, как только вызывается awk.И если awk не найдет никакого другого блока, кроме BEGIN, он выполнит эти BEGIN блоки и завершит работу.

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

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