sed 使用动态生成的字符串替换

sed uinsg dynamic generated string replacement

创建一个包含两行的文件a.tsv

echo aa bbb ccc ddd >a.tsv
echo xxxxxxxaa bbb ccc ddd >>a.tsv

用 shell 脚本中动态生成的字符串替换每一行 a.sh

#!/bin/bash
#get line number
l1=
l2=$(expr  + 1)
#input file name
fn=
#get string in l1 line
vv="{${l1},${l1}p;${l2}q}"

v1=$(sed -n ${vv} $fn )
echo $v1
#cut off 6 chars from the end of string v1
v2=${v1::-6}
echo $v2
#replace l1 line v1 with new line v2
vb="{s|${v1}|${v2}|g }"
echo $vb

sed -i -r  '$vb'  $fn

当我运行它是:

./a.sh 1 a.tsv

但我得到了那些输出:

怎么了?

aa bbb ccc ddd
aa bbb c
{s|aa bbb ccc ddd|aa bbb c|g }
sed: -e expression #1, char 3: expected newer version of sed

echo aa bbb ccc ddd >a.tsv 的输出不是 TSV(Tab-Separated 值)所以不要将其命名为 a.tsv,因为这会产生误导,如果需要,请使用 a.txt有一个后缀。

您无法轻松地使用 sed 稳健地完成您想做的事情,因为 sed 不理解文字字符串,请参阅 。您应该改用具有文字字符串功能的工具,例如 awk。

如果我正确理解了您的代码,那么您似乎正在尝试这样做:

$ cat a.txt
aa bbb ccc ddd
xxxxxxxaa bbb ccc ddd

$ cat a.sh
#!/usr/bin/env bash

awk -i inplace -v lineNr="" '
    NR == lineNr {
        [=11=] = substr([=11=],1,length()-6)
    }
    { print }
' ""

$ ./a.sh 1 a.txt

$ cat a.txt
aa bbb c
xxxxxxxaa bbb ccc ddd

以上是将 GNU awk 用于 -i inplace,就像您将 GNU sed 用于 -i(和 -r),但与 sed 解决方案不同,它适用于输入中的任何字符。