У меня есть большой файл данных, и я хочу разбить его на файлы поменьше на основе значений в столбце 1. Например, столбец 1 содержит числа от 1 до 10 десять раз, чтобы получить 100 строк, и я хочу, чтобы все строки с числами «1», «2» или «3» и т. д. были в отдельном файле (предпочтительно без сортировки). Кроме того, я не хочу запускать команду 10 раз, поэтому хочу, чтобы она была в цикле.
Мои файлы выглядят так:
Команда, которую я попробовал:
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.txt
for каждой строки 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».