我想用file1
每行中的值替换第 2、第 6 和第 7 行file2
,并生成一系列等于wc -l file2
cat file1
w
3
y
G
7
1.2
Q
cat file2
1 1 1
6 6 7
5 6 5
预期的结果:
cat out1
w
1
y
G
7
1
1
cat out2
w
6
y
G
7
6
7
cat out3
w
5
y
G
7
6
5
答案1
awk '
FNR == NR { data[++n] = $0; next }
{
data[2] = $1; data[6] = $2; data[7] = $3;
outname = sprintf("out%d", FNR) # or: outname = "out" FNR
for (i = 1; i <= n; ++i)
print data[i] >outname
close(outname)
}' file1 file2
这首先阅读file1
,然后file2
。
在读取file1
(FNR == NR
块)时,代码所做的唯一事情awk
是将每一行存储在数组中data
。
读取时file2
,代码将获取该文件的一行上的三个字段中的每一个,并将它们分配给与data
要更改的行相对应的索引file1
。
然后,存储的行将data
打印到通过获取当前行号file2
并在其前面添加字符串而构造的文件名out
。
close(outname)
仅当您使用awk
非 GNU 的awk
,并且写入的文件数量超过打开文件描述符的限制(超过ulimit -n
返回的数量,对于标准流减去三个)时,才真正需要。
测试:
$ tree
.
|-- file1
`-- file2
0 directory, 2 files
$ awk '
FNR == NR { data[++n] = $0; next }
{
data[2] = $1; data[6] = $2; data[7] = $3;
outname = sprintf("out%d", FNR)
for (i = 1; i <= n; ++i)
print data[i] >outname
close(outname)
}' file1 file2
$ tree
.
|-- file1
|-- file2
|-- out1
|-- out2
`-- out3
0 directory, 5 files
$ paste out[123]
w w w
1 6 5
y y y
G G G
7 7 7
1 6 6
1 7 5
答案2
$ cat tst.awk
BEGIN {
split("2 6 7",tmp)
for (fldNr in tmp) {
map[tmp[fldNr]] = fldNr
}
}
NR==FNR {
rows[++numRows] = $i
next
}
{
out = "out" FNR
for (rowNr=1; rowNr<=numRows; rowNr++) {
print (rowNr in map ? $(map[rowNr]) : rows[rowNr]) > out
}
close(out)
}
$ awk -f tst.awk file1 file2
$ head out?
==> out1 <==
w
1
y
G
7
1
1
==> out2 <==
w
6
y
G
7
6
7
==> out3 <==
w
5
y
G
7
6
5
答案3
使用GNU sed我们在文件 out_0/1/2 中获取 file2 每一行的输出。
tmpf=$(mktemp) i=0
while read -ra a <&3
do
printf '%s\n' "${a[@]}" > "$tmpf"
sed -ne "
$(printf '%dba\n' 2 6 7)
p;d;:a
R $tmpf
" file1 > "out_$i"
(( i++ ))
done 3< file2
- 在 while 循环中读取 file2 并将字段从空格分隔转换为换行符分隔并存储在临时文件中。
- get sed 对 file1 的第 2,6,&7 行调用 R 命令以获得所需的输出。