awk системный вызов с инвертированным эффектом

У меня есть файл данных с несколькими блоками данных, заключенными между определенными ключевыми словами ( DATA , END ). Я использую awk для извлечения блоков данных в отдельные файлы на основе имени файла, взятого из указанного блока. Поскольку некоторые блоки данных имеют одно и то же имя, я переименовываю каждый выходной файл с увеличением целого числа, если файл (« blockname ») уже существует:

 #cat input.file useless stuff1 DATA blockname1 data1 data1 END useless stuff2 DATA blockname2 data2 data2 END useless stuff3 DATA blockname1 data3 data3 END useless stuff4 

Ожидаемым будет три выходных файла blockname1 , blockname2 и blockname1_1 (обратите внимание, как последний файл имеет целое число, назначенное ему)

 #cat blockname1 DATA blockname1 data1 data1 END 

(другие соответственно …)

Теперь следующий скрипт работает так, как я хочу:

 awk 'BEGIN { FS=" +" } ; \ /DATA/,/END/ \ { if ( $1 ~ /DATA/ ) \ { block=$2 ; i=0 ; file=block ;\ while ( system("test ! -e " file ) ) \ { i++ ; file=block"_"i ; print file } \ } ; \ print $0 > file \ } ' \ input.file 

Моя проблема связана с циклом while и его системным вызовом:

Я ожидал, что system("test -e " file) будет ИСТИНА, когда file существовать, и будет FALSE, если file еще не существует, т.е. цикл while запускается только в том случае, если file присутствует и сломается, если (новый) file еще не существует.

Однако, если я использую system("test -e " file) (и делаю ее подробным с print file ), у меня есть бесконечный цикл с тем же именем с увеличением целочисленного суффикса, а противоположная system("test !-e " file) дает желаемый результат.

Таким образом, это ведет себя точно к тому, что я ожидал.

3 Solutions collect form web for “awk системный вызов с инвертированным эффектом”

Хорошо, я подумал: проблема кроется в разных определениях того, что ИСТИНА и ЛОЖЬ между состоянием выхода test и условием цикла while в awk .

Команда postive test выводит код выхода 0 для TRUE и отрицательный в 1 для FALSE.

Однако в awk цикл while интерпретирует 0 как FALSE и 1 как TRUE, так что точно противоположное определение.

В качестве примера:

 awk '{ while ( 0 ) ; { print "0" } }' file 

не будет производить какой-либо вывод, тогда как

 awk '{ while (1) ; { print "1" } }' file 

будет печатать бесконечные 1 с.

Таким образом, наилучшая практика должна быть явной в такой комбинации

 while ( system("command") == 0 ) 

или

 while ( system("command") == 1 ) 

соответственно.

Так что в моем случае

 while ( system("test -e " file ) == 0 ) 

показывает ожидаемое поведение.

awk system() возвращает статус завершения команды, которую вы запускаете, – 0 для успеха и! = 0, если не успех. Для простого примера вы можете попробовать запустить:

 v = system("date"); 

v будет 0

если вы запустите:

 v = system("dat"); 

v может быть 127 или значение отличное от 0, ошибка, возвращаемая ОС, если команда dat отсутствует или не найдена.

Если я понимаю вас, цель заключается в извлечении содержимого файла input.file в разные файлы, избегая потери блоков с тем же именем.

Если это так, и если целевой каталог всегда пуст до извлечения, то есть лучшее (и более быстрое) решение:

 awk ' /DATA/{ block=$2; n = blocks[block]++; file=block (n? "_" n: ""); } /DATA/,/END/{ print > file }' input.file 

Таким образом awk не нуждается в выполнении новой оболочки N раз, чтобы проверить, существует ли файл.

Заметки:

  • Нет необходимости в блоке BEGIN, потому что разделитель полей awk уже является пробелом.
  • В конце строк не нужно '\' , потому что одинарная кавычка уже многострочная.
  • Модернизирован, чтобы проверить ветвь по ошибке в debian ... как я могу вернуться к стабильной?
  • Правильное литье типов в сценарии оболочки для использования с циклом while и модулем
  • shell scripting - несколько тестов равенства в одном выражении if
  • Множественный оператор, который включает специальные символы, используя при возникновении ошибок
  • Bash - ожидаемое целочисленное выражение
  • `test` и` [`- разные бинарные файлы, любая разница?
  • Поймать неожиданный ввод одиночного символа в bash
  • Если условие не работает в скрипте над ssh
  • Linux и Unix - лучшая ОС в мире.