我想用数字序列替换文本文件中的字符串,例如 1 2 3 4 5 6 7 最好使用 sed。
这是我尝试过的(没有搜索字符串)并且似乎有效:
for i in {1..5};do echo $(seq 1 $i); done
输出:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
但是,当我尝试这样做时:
for i in {1..5};do sed -i "s/abc/$(seq 1 $i)/g" test; done
我收到以下错误:
sed: -e expression #1, char 8: unterminated `s' command
sed: -e expression #1, char 8: unterminated `s' command
sed: -e expression #1, char 8: unterminated `s' command
sed: -e expression #1, char 8: unterminated `s' command
我也尝试过将替换字符串括在括号中,但似乎不起作用。
第一个循环
for i in {1..5}
将被替换为文件名的 glob,我想在其中替换一些参数。
答案1
TL;博士:
有一些方法可以解决这个问题,我认为最适合您的示例案例的是:
for i in {1..5};do sed -i "s/abc/$(seq -s ' ' 1 $i)/g" test; done
即:我们要求seq
用一个空格来分隔每个数字。
解释:
您收到这些错误的原因是因为输出:
seq 1 5
不是:
1 2 3 4 5
反而:
1
2
3
4
5
既然你附上了$(seq 1 $i)
命令替换双引号内,通常分词不执行,因此实用程序输出的所有换行符(最后一个除外)seq
都保留原样。
因此实际的sed
命令变成了:
sed -i "s/abc/1
2
3
4
5
/g" test
这是不被接受的,因为就目前而言sed
,您向它提供了一个s/abc/1
命令,即缺少所需的 Final /
。
Anecho $(seq 1 5)
确实会打印,1 2 3 4 5
因为$(seq 1 5)
不在双引号内,因此按照 shell 的默认行为发生分词。
我们确实可以修复您的示例案例,如下所示:
for i in {1..5};do sed -i "s/abc/$(echo $(seq 1 $i))/g" test; done
也就是说,通过执行命令替换(您原来的seq 1 $i
)里面另一个命令替换(echo
一个)。
即使在双引号内,这也有效,因为$(echo ...)
命令替换是在子外壳这是不是处于“I-am-inside-a-double-quote”状态,因此对输出进行分词seq
将要在那里进行。
答案2
您可以将输出通过管道传输到临时文件,然后将临时文件移至原始文件之上。还有,你可能本来打算一次只操作一行,在这种情况下,您应该删除g
:
for i in {1..5}; do
sed -e "s/abc/$(seq 1 $i)/" test > test.tmp
mv test.tmp test
done