Как выполнить команду в цикле по значениям столбца файла?

У меня есть такая простая команда

 grep 'X' results.dat | awk '{print $NF}'  > Y.dat

Я хочу зациклить эту команду, взяв Xs из столбца 1 и соответствующие Ys из столбца 2 того же файла например. Файл NAMES

NAMES имеет формат

C11-C12     p01
C13-C14-C17 P02
etc ..

, поэтому первые два шага цикла должны быть такими:

grep 'C11-C12' results.dat | awk '{print $NF}'  > p01.dat
grep 'C13-C14-C17' results.dat | awk '{print $NF}'  > p02.dat
-1
02.12.2016, 01:24
2 ответа

Решение, которое не требует цикла в оболочке:

awk 'pass==1 {  Xpatt[NR] = $1; Yfile[NR] = $2 ".dat"; printf "" > Yfile[NR] }
     pass==2 {
                for (i in Xpatt) {
                        if ($0 ~ Xpatt[i]) print $NF > Yfile[i]
                }
             }' pass=1 NAMES pass=2 results.dat
  • Прежде всего, awk позволяет вам указывать назначения переменных в качестве аргументов командной строки, {{1} } после программы, смешанные с именами файлов, без использования -v . Они выполняются в той точке последовательности обработки , которую предлагает их позиция в командной строке. Итак, в приведенной выше команде

    1. pass получает установлено значение 1,
    2. обрабатывается файл NAMES ,
    3. pass получает значение 2, а затем
    4. обрабатывается файл results.dat .

    Думаю, я мог бы установить pass = 1 с помощью -v или в блоке BEGIN .

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

    (Строго говоря, я полагаю, что этот сценарий должен проверять, является ли какой-либо из файлов пустым, потому что в этом случае работать не нужно.)

  • Хотя pass == 1 (мы читаем файл NAMES ), сохраняем значения X и Y (шаблон и имя файла) из столбцов 1 и 2 ( $ 1 и $ 2 ) этого файла. Создайте выходной файл ( Yfile [NR] ), потому что, если мы этого не сделаем здесь, мы не получим (пустые) выходные файлы {{1} } для шаблонов, которых нет в файле results.dat . (Если вас это устраивает, опустите инструкцию printf .)
  • Пока pass == 2 (мы читаем файл results.dat ), перебирает шаблоны в NAMES ] файл и выведите последнее слово из каждой строки, которая соответствует шаблону , в соответствующий файл - то есть, эквивалент OP grep X… | awk '{print $ NF}'> команда Y.dat .
3
28.01.2020, 05:07

Решение на Bash:

while read X Y remainder || [[ -n ${Y} ]]; do
    awk -v X="$X" '$0 ~ $X {print $NF}' results.dat > "$Y".dat
done < NAMES
  • Обычно , когда IFS = "q", читается остаток XY; делать ...; done будет перебирать строки из NAMES . Он разделит значения в каждой строке на основе значения IFS (внутренний разделитель полей). В этом примере IFS установлен на букву q . IFS по умолчанию использует пробелы (пробелы, табуляции или новые строки). Первому полю присваивается переменная X , второму - Y , а остальной части строки - остатку .

    См. Также: Чтение столбцов из файла в отдельные переменные (Unix.SE).

    В приведенном выше решении IFS не указан, потому что я предполагаю , что ваши поля уже разделены пробелами.

    Примечание: если поля в вашем файле NAMES содержат обратную косую черту, вам необходимо использовать read -r , чтобы предотвратить чтение от интерпретации обратной косой черты как escape-последовательности. .

  • ...остаток || [[-n $ {остаток}]] часть обрабатывает две вещи: любые дополнительные поля, если таковые имеются, сохраняются в остатке ; и обрабатывает случай, если последняя строка вашего входного файла не заканчивается новой строкой \ n ( read возвращает ненулевой код выхода при обнаружении EOF).

    См. Также: Прочитать файл построчно, присвоив значение переменной (SO).

  • Полностью удалить grep : awk -v X = "$ X" '$ 0 ~ $ X {print $ NF}' results.dat> "$ Y" .dat . Параметр -v для awk определяет переменную, которая может использоваться в сценарии awk .

1
28.01.2020, 05:07

Теги

Похожие вопросы