Bash 使用sed在大量文件中搜索特定字符串并替换它

Bash 使用sed在大量文件中搜索特定字符串并替换它,bash,sed,Bash,Sed,我试图做的是在大量源文件中搜索一个特定的模式,并将另一个表达式放在这个模式中。我正在查找的文件都具有相同的扩展名*.F90。 我的第一步是使用grep并查找包含allocate但未分配的文件的所有行,因此我有: grep –I “ allocate *(” *.F90 | grep –v allocated 我遇到的第一个问题是,括号前面可能有一个或多个空格。我可以 allocate( or allocate ( or allocate ( 这就是为什么我需要grep命令中的

我试图做的是在大量源文件中搜索一个特定的模式,并将另一个表达式放在这个模式中。我正在查找的文件都具有相同的扩展名*.F90。 我的第一步是使用grep并查找包含allocate但未分配的文件的所有行,因此我有:

grep –I “ allocate *(” *.F90 | grep –v allocated
我遇到的第一个问题是,括号前面可能有一个或多个空格。我可以

 allocate( 
 or allocate ( 
 or allocate  (  
这就是为什么我需要grep命令中的“*”。 然而,一般规则(除了空格外)说分配后面跟着“(”然后是分配的东西。所以我有:

allocate ( array_name ( .... 
同样,空格是可选的 所以我想做的是找到这个字符串,在它前面放上以下内容:

If( allocated(array_name) ) deallocate(array_name)
sed -i.bk -e '/allocated/t' \
  -e 's/allocate *( *\([A-Za-z0-9_]*\) *)/If( allocated(\1) ) deallocate(\1) &/' \
  *.F90
在这之后的下一行,我想让原始字符串
allocate(array(…..

请注意,数组_名称是一个字母数字字符串,它在替换后出现在多个位置。它是所定位数组的名称。
如果有人能给我一个提示,我将不胜感激。我被卡住了,不知道怎么做。

我想你的意思是想用
if(allocated(array\u name))deallocate(array\u name)allocate(array\u name)
替换
if(allocated(array\u name))deallocate(array\u name)allocate(array\u name)

在GNU或BSD sed中,您可以执行以下操作:

If( allocated(array_name) ) deallocate(array_name)
sed -i.bk -e '/allocated/t' \
  -e 's/allocate *( *\([A-Za-z0-9_]*\) *)/If( allocated(\1) ) deallocate(\1) &/' \
  *.F90
这将搜索并替换*.F90中的匹配行,并使用分配打开跳过行。原始文件将被称为*.F90.bk

正如@Anders Johansson提到的,在其他情况下,要分配的参数不是alphanum下划线,那么您可以在搜索和替换之前搜索它:

for i in *.F90; do
    echo "$i"
    sed -n '/.*allocate *( *\([^ )]*\) *).*/{h; s//\1/; /^[A-Za-z0-9_]*$/t
        x; p;}' "$i"
done
(注意
t
之后的换行符,BSD sed将t之后的所有内容解释为标签)。在bash中按ctrl+v ctrl+j在命令行上输入换行符

  • /a\(b\)c/
    查找具有匹配字符串的行
  • h
    *h*将匹配的
    abc
    放入保留空间
  • s//\1/
    *s*用第一组
    b
  • /^[a-z]*$/t如果
    b
    匹配
    ^[a-z]*$
    ,则分支到脚本末尾
  • x
    e*x*更改保持空间
    abc
    a模式空间
    b
  • p
    *p*打印模式空间
    b

这在一般情况下有点棘手-例如,如果有
分配(…)
在表达式中的情况(如
something=allocate(…)
array\u name
是表达式(如
分配(get\u buffer())
)。