将文件中的字符串替换为另一个文件中的字符串,两者都保存在变量中

将文件中的字符串替换为另一个文件中的字符串,两者都保存在变量中

我想用另一个字符串替换文件中找到的字符串,但两者都有一个特殊字符(在本例中它是一个.字符),例如1.02.0

这是当前使用的命令:

sed -i 's/1\.0/2\.0/g' /home/user1/file1.txt

如果1.02.0保存在变量$iand中会怎样$j?哪里i有价值1.0j有价值2.0,我还能用什么i代替j

答案1

您可以使用它sed来为您进行修复:

printf '%s\n' "$i" "$j" |
sed 's/[]\$*&/.^[]/\\&/g;H;$!d
     x;y|\n|/|;s|.*|s&/g|' |
sed -f - /path/to/infile

因此,此s///替换将转义输入中的任何/所有 BRE 元字符:

s/[]\$*&/.^[]/\\&/g

...通过在每个前面加上反斜杠作为前缀。然后,第一个通过在其前面添加 ewline 字符sed,将第一行 - $i- 的副本保存在H旧空间中\n$i然后该行被d删除,因为它!不是$最后一行。下一行 - 该$j行 - 也是最后一行,在它得到与第一行相同的处理后,它是不是 d已入选。相反,它会x更改保持缓冲区和模式缓冲区并对连接的结果进行操作。此时模式空间看起来像:

\n1\.0\n2\.0

...所以我们y///将所有的\n行转换为/斜线,用模式空间本身s///替换所有的内容,再加上一个前缀和一个后缀,这样我们得到:.*&s/g

s/1\.0/2\.0/g

然后,它会自动打印到第二个sed正在读取 stdin - 或-f -- 作为其脚本的文件。当第一个sed完成并关闭它们之间的管道时,第二个sed开始应用......

s/1\.0/2\.0/g

...其命名输入文件中的每一行 - 位于此处/path/to/infile

我这样写了你的文件:

printf '%04s%04s%04s%04s\n' \
        0 0 -1 0 1 0 0 0 0 -1\
        0 0 1.5 2.0 1.0 0 >/tmp/temp

这给了我一个像......

   0   0  -1   0
   1   0   0   0
   0  -1   0   0
 1.5 2.0 1.0   0

然后我写了一个不同版本的脚本,例如:

ii=0.0
for i in        1.0 2.0 3.0 4.0
do      str2=$i
        printf '\033[41m## %s \033[0m\n' \
                "str2 = $str2" "$ii $str2"
        printf %s\\n "$ii" "$str2"
        ii=$str2
done | 
sed '   s/[]\$^&*./[]/\\&/g;H;x
        s|^\(\n\)\(.*\)\n\(.*\)\n\(.*\)\n\(.*\)|\
        bs\5\1:i\5\1i\\\1\2\\\1\3\1:s\5\1s/\4/\5/gp;ti\5|p
        s|||;h;d' |
sed -f - /tmp/temp

它仅使用 shell 生成字符串,但允许sed执行所有数据处理。请注意,虽然sed调用了两个,但每个仅被调用一次。

当我运行它时,结果是:

   0   0  -1   0
   1   0   0   0
   0  -1   0   0
 1.5 2.0 2.0   0
## str2 = 2.0 
## 1.0 2.0 
 1.5 3.0 3.0   0
## str2 = 3.0 
## 2.0 3.0 
 1.5 4.0 4.0   0
## str2 = 4.0 
## 3.0 4.0 
 1.5 4.0 4.0   0

以 开头的行#是红色的,正如我所期望的那样。仅当替换成功sed时才写入它们。s///第一个为第二个编写的脚本sed如下所示:

                bs1\.0
:i1\.0
i\
[41m## str2 = 1\.0 [0m\
[41m## 0\.0 1\.0 [0m
:s1\.0
s/0\.0/1\.0/gp;ti1\.0

                bs2\.0
:i2\.0
i\
[41m## str2 = 2\.0 [0m\
[41m## 1\.0 2\.0 [0m
:s2\.0
s/1\.0/2\.0/gp;ti2\.0

                bs3\.0
:i3\.0
i\
[41m## str2 = 3\.0 [0m\
[41m## 2\.0 3\.0 [0m
:s3\.0
s/2\.0/3\.0/gp;ti3\.0

                bs4\.0
:i4\.0
i\
[41m## str2 = 4\.0 [0m\
[41m## 3\.0 4\.0 [0m
:s4\.0
s/3\.0/4\.0/gp;ti4\.0

请注意,虽然看起来字符串[没有转义,但这只是我的终端对输出的影响 - 它最终会立即吃掉紧随其后的 char \033。当第二个sed接收到脚本时,输入是这样的\033\[...,但它插入到标准输出的输出i\033[...

答案2

试试这个:全部转义。将全部替换.\.

str1="$( echo -n $i | sed 's/\./\\\./g' )"  

对 str2 重复相同的操作$j。然后替换如下

sed "s/$str1/$str2/g"

相关内容