当我尝试使用 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