用变量替换模式

用变量替换模式

我在一个变量中存储了 3 行数字,我需要用它来替换我已使用并存储在另一个变量中$new的文件中的 3 行。我想。但我收到错误:grep$oldsed "s/$old/$new/g" input > output

sed: 1: "s/\( 28.47969107 0. ...": unterminated substitute pattern

我的输入文件如下所示:

scale
 1.000
primitive lattice vectors
    28.47969107  0.00000000  0.00000000
   0.00000000 28.47969107  0.00000000
   0.00000000  0.00000000 28.47969107
grid dimensions
  100 100 100

我的$old是线条

28.47969107 0.00000000 0.00000000 0.00000000 28.47969107 0.00000000 0.00000000 0.00000000 28.47969107

$new与旧的格式相同,只是数字不同。

答案1

sed -e "/$old/i$new" -e "/$old/{N;N;d}" input > output

在哪里

  • $old可以是28.47969107第一行,也可以是第一行28.47969107 0.00000000 0.00000000
  • $new应该是形式28.47969107 0.00000000 0.00000000\n0.00000000 28.47969107 0.00000000\n0.00000000 0.00000000 28.47969107

其他方式(如果你有新的 GNU sed (版本 >4.2.1)和选项)在变量中-z转义:newline

sed -z "s/$(printf "%b" "$old"|sed '$!s/$/\\/')/$(printf "%b" "$new"|sed 's/$/\\/')/" input > output

或者,如果您在脚本分配函数中进行替换

end_esc(){ printf "%b" "$@"|sed '$!s/$/\\/' ; }
sed -z "s/$(end_esc $old)/$(end_esc $new)/" input > output

答案2

首先,让我们定义一个示例字符串new

$ new=$'1 2 3\n4 5 6\n7 8 9'

现在,让我们删除后面的三行primitive lattice vectors并将其替换为new

$ awk -v "new=$new" 'f==1{print new} f{f--;next} {print} /primitive/{f=3}' input
scale
 1.000
primitive lattice vectors
1 2 3
4 5 6
7 8 9
grid dimensions
  100 100 100

答案3

sed -e '$!N;$b' -e "/\n.*\n/!N;s/$old/$new/;t" -e P\;D

上面的代码可以工作,但有一个问题:换行符 in$old需要表示为\n,换行符 in$new前面应该有一个\反斜杠。你的价值观中的换行符给你带来了麻烦。例如,扩展后:

sed 's/24.0000000001
.000000000000
.0000000000/...'

...不起作用。那是一个未终止的正则表达式- 你看?

反而:

old='num\nnum\nnum'
new='num\
num\
num'

...就是你所需要的。

如果出于某种原因,您发现自己逃避变量很麻烦,那么您可以执行以下操作:

(  set -f; IFS='
'; printf '%s\\n' / .* '/!N;s/'$old
   printf '%s\\\n' */$new"/;t$IFS#"
)| sed -e '$N;$b' -f - -e P\;D input > output

但这取决于两个变量中没有空行,而且可能并不容易。

答案4

sed s/"$old"/"$new"/g为我工作

相关内容