Bash

將文件中的字元串替換為另一個都保存在變數中的字元串

  • March 12, 2015

我想用另一個字元串替換文件中找到的字元串,但兩者都有一個特殊字元(在本例中是一個.字元),例如1.02.0.

所以這是目前使用的命令:

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

如果1.02.0被保存在變數$i和中$j怎麼辦?哪裡i有價值1.0,哪裡j有價值2.0,我還能i用什麼來代替j

您可以使用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

…通過在每個前面加上反斜杠。然後第sed一個將第一行的副本保存$iH舊空間中,方法是在其前面添加一個\newline 字元。然後刪除該$i行,d因為它!不是$最後一行。下一行 -$j行 - 也是最後一行,在得到與第一行相同的處理後,它不會 d被刪除。相反,它x會更改保持和模式緩衝區並對連接的結果進行操作。此時模式空間看起來像:

\n1\.0\n2\.0

…所以我們y///將所有ewlines轉換\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進行所有數據處理。請注意,儘管呼叫了兩個seds,但每個只呼叫一次。

當我執行它時,結果是:

  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[...

引用自:https://unix.stackexchange.com/questions/189651