例如,file.txt 中唯一的内容如下所示:
xxxxxxxxxHAHAxxxxxxHOHOxxxxxxx
我希望用 seq 1 3 替换 HAHA,用 seq 5 7 替换 HOHO,所以输出应该是:
xxxxxxxxx1xxxxxx5xxxxxxx
xxxxxxxxx2xxxxxx6xxxxxxx
xxxxxxxxx3xxxxxx7xxxxxxx
我做了什么:
for i in $(seq 1 3)
do sed "s/HAHA/$i/g" file.txt
for i in $(seq 5 7)
do sed "s/HOHO/$i/g" file.txt
done
done > new.txt
但 new.txt 没有显示我所期望的。我应该如何更改代码?
答案1
这是一种方法,可以使用bash
内置read
命令读取不同文件描述符的功能:
while read -u3 i && read -u4 j; do
sed -e "s/HAHA/$i/" -e "s/HOHO/$j/" file.txt
done > new.txt 3< <(seq 1 3) 4< <(seq 5 7)
seq
由于您的数字具有简单的算术关系,因此使用单个进程+一些 shell 算术会更简单:
for i in $(seq 1 3); do
sed -e "s/HAHA/$i/" -e "s/HOHO/$((i+4))/" file.txt
done > new.txt
无论哪种情况,请参阅为什么使用 shell 循环处理文本被认为是不好的做法?- 对于您提供的最小示例来说,效率低下可能并不重要,但如果您正在做更严肃的事情,您应该考虑使用不同的方法。
答案2
无需为生成的每行调用外部实用程序:
read template <file
paste <(seq 1 3) <(seq 5 7) |
while read x y; do
t=${template/HAHA/$x}
t=${t/HOHO/$y}
printf '%s\n' "$t"
done >new.txt
file
这首先从名为into 的文件中读取行$template
。然后它为循环构造一个两列输入while read
。循环的输入是来自 的两列数字seq
。
在循环中,bash
对 的值执行一些特定的替换,以将和字符串$template
替换为从 读取的数字。这将创建然后输出。HAHA
HOHO
paste
$t
仅使用awk
,并假设输入仅为一行:
awk '{
for (i = 1; i <= 3; ++i) {
t = $0;
sub("HAHA", i, t)
sub("HOHO", 4+i, t)
print t
}
}' file
一个 shell 循环 for bash
,模仿awk
上面的代码:
read template <file
for (( i = 1; i <= 3; ++i )); do
t=${template/HAHA/$i}
t=${t/HOHO/$((i+4))}
printf '%s\n' "$t"
done