我有一个大型数据文件,想根据第 1 列的值将其拆分为较小的文件。例如,第 1 列有 1 到 10 的数字 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
ID.txt
ID.txt
awk
awk 'NR==FNR{a[$1]++; next} ($1 in a){print >> $1".txt"}' ID.txt test.txt
上述代码将 的第一个字段保存ID.txt
在数组 中a
。NR
和FNR
是特殊awk
变量,表示“输入流的当前行”和“当前文件的当前行”。 只有在读取第一个文件时,这两个变量才会相等。 因此,NR==FNR{a[$1]++; next}
只会在第一个文件的行上运行。 第二部分将不会被执行,因为 指示next
跳到awk
下一行。
第二部分,检查当前行的第一个字段(记住,这只在第二个文件上运行)是否存在于数组中a
(这意味着它在ID.txt
),如果存在,则将该行打印到名为“field1.txt”的文件中