将 for 循环元素的数量传递给外部命令
Pass number of for loop elements to external command
我正在使用 for 循环遍历目录中的 .txt 文件并从文件中获取指定的行。之后输出被传递给 pr
命令,以便将其打印为 table。一切正常,但我手动指定 table 应包含的列数。当文件数量不固定时,这很麻烦。
我正在使用的命令:
for f in *txt; do awk -F"\t" 'FNR ~ /^(2|6|9)$/{print }' $f; done | pr -ts --column 4
我应该如何修改命令以将“4”替换为元素编号?
编辑:
基本问题是是否可以提供匹配的文件编号以在循环外运行。看到解决方案,我想不可能解决这个问题。在此结论之前,文件的结构并不真正相关。
但是,考虑到上述因素,我提供了以下文件结构。
样本file.txt:
Irrelevant1 text
Placebo 1222327
Irrelevant1 text
Irrelevant2 text
Irrelevant3 text
Treatment1 105956
Irrelevant1 text
Irrelevant2 text
Treatment2 49271
Irrelevant1 text
Irrelevant2 text
for
循环从 4 个 *txt
文件生成以下内容:
1222327
105956
49271
969136
169119
9672
1297357
237210
11581
1189529
232095
13891
预期 pr
使用动态生成的输出 --column 4
:
1222327 969136 1297357 1189529
105956 169119 237210 232095
49271 9672 11581 13891
您可以 运行 ls 并将输出通过管道传输到 wc -l。然后一旦你得到那个数字,你就可以将它分配给一个变量并将该变量放在你的命令中。
num=$(ls *.txt | wc -l)
我忘记了如何在 AWK 中放置 bash 变量,但我认为您可以做到。如果没有,请回复,我会尝试找到不同的答案。
假设:
- 所有输入文件生成相同数量的输出行(否则我们可以添加一些代码来跟踪最大行数并根据需要生成空白列)
设置(列为 tab-delimited):
$ grep -n xxx f[1-4].txt
f1.txt:6:xxx 1222327
f1.txt:9:xxx 105956
f1.txt:24:xxx 49271
f2.txt:6:xxx 969136
f2.txt:9:xxx 169119
f2.txt:24:xxx 9672
f3.txt:6:xxx 1297357
f3.txt:9:xxx 237210
f3.txt:24:xxx 11581
f4.txt:6:xxx 1189529
f4.txt:9:xxx 232095
f4.txt:24:xxx 13891
使用 awk
动态构建 'table' 的一个想法(替换 OP 当前的 for
循环):
awk -F'\t' '
FNR==1 { c=0 }
FNR ~ /^(6|9|24)$/ { ++c ; arr[c]=arr[c] (FNR==NR ? "" : " ") }
END { for (i=1;i<=c;i++) print arr[i] }
' f[1-4].txt | column -t -o ' '
注意: 我们将继续让 column
用一个 space 来处理 pretty-printing table ] 分隔列,否则我们可以使用 spaces
添加更多代码到 awk
到 right-pad 列
这会生成:
1222327 969136 1297357 1189529
105956 169119 237210 232095
49271 9672 11581 13891
我正在使用 for 循环遍历目录中的 .txt 文件并从文件中获取指定的行。之后输出被传递给 pr
命令,以便将其打印为 table。一切正常,但我手动指定 table 应包含的列数。当文件数量不固定时,这很麻烦。
我正在使用的命令:
for f in *txt; do awk -F"\t" 'FNR ~ /^(2|6|9)$/{print }' $f; done | pr -ts --column 4
我应该如何修改命令以将“4”替换为元素编号?
编辑: 基本问题是是否可以提供匹配的文件编号以在循环外运行。看到解决方案,我想不可能解决这个问题。在此结论之前,文件的结构并不真正相关。 但是,考虑到上述因素,我提供了以下文件结构。
样本file.txt:
Irrelevant1 text
Placebo 1222327
Irrelevant1 text
Irrelevant2 text
Irrelevant3 text
Treatment1 105956
Irrelevant1 text
Irrelevant2 text
Treatment2 49271
Irrelevant1 text
Irrelevant2 text
for
循环从 4 个 *txt
文件生成以下内容:
1222327
105956
49271
969136
169119
9672
1297357
237210
11581
1189529
232095
13891
预期 pr
使用动态生成的输出 --column 4
:
1222327 969136 1297357 1189529
105956 169119 237210 232095
49271 9672 11581 13891
您可以 运行 ls 并将输出通过管道传输到 wc -l。然后一旦你得到那个数字,你就可以将它分配给一个变量并将该变量放在你的命令中。
num=$(ls *.txt | wc -l)
我忘记了如何在 AWK 中放置 bash 变量,但我认为您可以做到。如果没有,请回复,我会尝试找到不同的答案。
假设:
- 所有输入文件生成相同数量的输出行(否则我们可以添加一些代码来跟踪最大行数并根据需要生成空白列)
设置(列为 tab-delimited):
$ grep -n xxx f[1-4].txt
f1.txt:6:xxx 1222327
f1.txt:9:xxx 105956
f1.txt:24:xxx 49271
f2.txt:6:xxx 969136
f2.txt:9:xxx 169119
f2.txt:24:xxx 9672
f3.txt:6:xxx 1297357
f3.txt:9:xxx 237210
f3.txt:24:xxx 11581
f4.txt:6:xxx 1189529
f4.txt:9:xxx 232095
f4.txt:24:xxx 13891
使用 awk
动态构建 'table' 的一个想法(替换 OP 当前的 for
循环):
awk -F'\t' '
FNR==1 { c=0 }
FNR ~ /^(6|9|24)$/ { ++c ; arr[c]=arr[c] (FNR==NR ? "" : " ") }
END { for (i=1;i<=c;i++) print arr[i] }
' f[1-4].txt | column -t -o ' '
注意: 我们将继续让 column
用一个 space 来处理 pretty-printing table ] 分隔列,否则我们可以使用 spaces
awk
到 right-pad 列
这会生成:
1222327 969136 1297357 1189529
105956 169119 237210 232095
49271 9672 11581 13891