sed 不替换 while 循环中的变量

sed 不替换 while 循环中的变量

当我尝试使用 sed 中变量的行号时,它可以单独工作,但是当使用 while 循环完成相同操作时,它不起作用。

例如。

cat file
den 
run
ten
run
fan

linenumber=2
replacetext=34
sed -i ""$linenumber"s/run/run\n"$replacetext"/" file

Output:
cat file
den
run
34
ten
run
fan

上面的作品和 sed 命令是在变量扩展后生成的。

但是当我在 while 循环中使用相同的方法时,它仅适用于第一个实例,而不适用于所有实例,因为我想使用纯 sed 解决方案用递增的行号替换所有实例。不需要 awk 或 perl 解决方案。

例如。

replacetext=1
while read in; do replacetext=$((replacetext++)) && sed ""$in"s/run/run\n"$replacetext"/" file; done <<< "$(cat file | grep 'run' -n | cut -f1 -d ':')"

预期输出:匹配文本将替换为自身,后跟换行符和递增数字。

den 
run
2
ten
run
3
fan

获得的输出:

den
run
2
ten
run
fan

请仅需要基于 sed 的解决方案。我想知道 while 循环中发生了什么异常行为,它不起作用。因为循环变量被赋予了行号的值,然后该行号在 sed 中用于替换该行上的 macthed 文本,其后是换行符和递增的数字。

当提供相同的变量行号时,Sed 似乎可以工作,但在 while 循环中使用时则不行。

答案1

它失败了,因为 <<< 之后的内容获取了正确行号的列表在原始文件中

然后你多次编辑该文件,插入额外的行

所以除了第一个之外的每个 sed 都被告知错误的行号对于 s/// 命令。

一种解决方案是反转行号列表,因此编辑不会影响之前的编号。

这是一个 sed 解决方案,在一个管道中,有点古怪。

第一个 sed 使用 = 运算符获取找到模式的行号。 nl 在每一行前面加上一个序列号:就像3 10

第二个 sed 输出 sed 表达式:它将每个这样的行转换为您所需的 sed 编辑,例如:10 s/$/\n3/

第三个 sed 收集并应用来自 stdin 的这些编辑,并对文件进行就地编辑。在这种情况下,它会自行编辑。

这是脚本本身:

#! /bin/bash

Pattern="[Ss]ed"

RegEx='[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*'
DoSed='\2 s/\$/\\n\1/'

sed -n -e "/${Pattern}/=" badSed |
    nl -ba |
    sed -e "s:${RegEx}:${DoSed}:" |
    sed -i -f - badSed
 

这就是它对自己所做的事情:

#! /bin/bash

Pattern="[Ss]ed"

RegEx='[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*'
DoSed='\2 s/\$/\\n\1/'
1

sed -n -e "/${Pattern}/=" badSed |
2
    nl -ba |
    sed -e "s:${RegEx}:${DoSed}:" |
3
    sed -i -f - badSed
4

答案2

需要替换的地方的行号被弄乱了。

因此,我们设计了另一种策略,我们允许 while 循环首先生成一组有效的 sed 命令,然后将其应用回输入文件。

replacetext=1
while read in; do ((replacetext++)); echo "$in s/\$/\\n$replacetext/"; done <<<"$(grep -n run file | cut -d: -f1)" | sed -f - file > tmp && mv tmp file 

相关内容