Проблема извлечения данных из файла с помощью awk

Проблема извлечения данных из файла с помощью awk

У меня есть большой файл данных, и я хочу разбить его на файлы поменьше на основе значений в столбце 1. Например, столбец 1 содержит числа от 1 до 10 десять раз, чтобы получить 100 строк, и я хочу, чтобы все строки с числами «1», «2» или «3» и т. д. были в отдельном файле (предпочтительно без сортировки). Кроме того, я не хочу запускать команду 10 раз, поэтому хочу, чтобы она была в цикле.

Мои файлы выглядят так:

  • text.txt

    введите описание изображения здесь

  • ID.txt

    1
    2
    3
    4
    

Команда, которую я попробовал:

cat ID.txt | while read line; do awk '$1 == ${line}' test.txt >$line.txt;done

Итак, подведем итог: я хочу, чтобы он считывал значение из файла ID.txt, например, «1», а затем извлекал все строки с «1» в первой строке и помещал их в файл с именем 1.txt, затем он перешел к 2, затем к 3, затем к 4 и т. д.

Но, как мне кажется, часть '$1 == ${line}' не работает.

решение1

Вы ищете -vвозможность awk:

   -v var=val
   --assign var=val
          Assign the value val to the variable var,  before  execution  of
          the  program  begins.  Such variable values are available to the
          BEGIN rule of an AWK program.

Что-то вроде этого:

cat ID.txt | 
    while read line; do awk -vline="$line" '$1 == l' test.txt >"$line".txt;done

Что было бы лучше выразить так (избегая бесполезного использования слова cat):

while read line; do 
    awk -vline="$line" '$1 == l' test.txt >"$line".txt;
done < ID.txt

Однако это очень медленно и неэффективно. Вы запускаете команду awkдля всего test.txtfor каждой строки ID.txt. Почему бы просто не прочитать ID.txtего awkи не вывести соответствующие строки:

awk 'NR==FNR{a[$1]++; next} ($1 in a){print >> $1".txt"}' ID.txt test.txt 

Вышеприведенный код сохраняет 1-е поле ID.txtв массиве a. NRи FNRявляются специальными awkпеременными, означающими «текущую строку входного потока» и «текущую строку текущего файла». Эти две переменные будут равны друг другу только при чтении первого файла. Поэтому NR==FNR{a[$1]++; next}будет запущен только на строках первого файла. Вторая часть не будет выполнена, поскольку nextуказывает awkперейти к следующей строке.

Вторая часть проверяет, существует ли первое поле текущей строки (помните, это выполняется только для второго файла) в массиве a(что означает, что оно было в ID.txt), и, если это так, выводит строку в файл с именем «field1.txt».

Связанный контент