Bash sed:用跨1行或多行的变量替换模式中的单词

Bash sed:用跨1行或多行的变量替换模式中的单词,bash,sed,Bash,Sed,我正在编写一个bash脚本,它将扫描PHP文件列表以查找特定的“classx扩展Y”字符串,并用我选择的另一个字符串(Z)替换Y X对我来说是未知的,它对于每个文件都是不同的(我不需要) 要知道它是什么,只知道它存在) Y是已知的,必须匹配才能进行替换 Z也是已知的(显然) 到目前为止,我已经成功地提出了一个sed行,如果整个类X扩展Y模式在一行上,它就可以工作,但是我似乎无法让它工作,例如,在X之后有一个换行,在下一行后面有一个“extends”(在某些情况下是以制表符/空格开头)。我想“

我正在编写一个bash脚本,它将扫描PHP文件列表以查找特定的“classx扩展Y”字符串,并用我选择的另一个字符串(Z)替换Y

  • X对我来说是未知的,它对于每个文件都是不同的(我不需要) 要知道它是什么,只知道它存在)
  • Y是已知的,必须匹配才能进行替换
  • Z也是已知的(显然)
到目前为止,我已经成功地提出了一个sed行,如果整个类X扩展Y模式在一行上,它就可以工作,但是我似乎无法让它工作,例如,在X之后有一个换行,在下一行后面有一个“extends”(在某些情况下是以制表符/空格开头)。我想“类”、X、“扩展”和Y可能在4行上,并且仍然是有效的PHP?我不知道

到目前为止,我的sed行如下所示(这是一个循环的内部):

在上面的行中,$OLDMODEL是Y,$NEWMODEL是Z,$FILELOC是要更改的文件的绝对路径。匹配后,该命令将在记录脚本名称、更改日期/时间以及替换类的更改行上方插入注释

我在网上看到的大多数关于多行模式匹配的教程似乎都使用了sed-e而不是-e,这给我带来了变量替换和其他仅适用于扩展regexp的问题

十、 Y和Z是带下划线的字母字符串,例如,某些类型的东西

如果有人能给我帮助,我将不胜感激。提前感谢:)

我意识到我可能会使用perl或python,但如果在sed中有可能的话,我希望能够让它工作,特别是在单行替换工作正常的情况下

样本输入:

 1. class FooModule_Sales_Model_Quote extends BarModule_Some_Other_Class
 2. class FooModule_Sales_Model_Quote
            extends BarModule_Some_Other_Class
 1. class FooModule_Sales_Model_Quote extends New_Module_Better_Class
 2. class FooModule_Sales_Model_Quote extends New_Module_Better_Class
样本输出:

 1. class FooModule_Sales_Model_Quote extends BarModule_Some_Other_Class
 2. class FooModule_Sales_Model_Quote
            extends BarModule_Some_Other_Class
 1. class FooModule_Sales_Model_Quote extends New_Module_Better_Class
 2. class FooModule_Sales_Model_Quote extends New_Module_Better_Class

使用带有
-z
选项的GNU,您可以:

sed -z 's@class[[:space:]]\+'"$X"'[[:space:]]\+extends[[:space:]]\+'"$Y"'\([[:space:]{]\)@class '"$X"' extends '"$Z"'\1@g'
测试日期:

请注意,您可以在输入中保留换行符,只需
\([[:space:]\+\)
将它们保存在backreference中,并将引用保存在替换的字符串中

我还添加了对空格或
{
behind
扩展了$Y
类名。正则表达式可能会匹配部分类,例如。您可能希望用
BarModule\u Some
替换某些内容,用
BarModule\u Some\u Other\u类
替换其他内容。因此,
sed
在一个正则表达式中不匹配这两个内容,您需要匹配下一个字符在类名后面加上一个


如果没有gnu sed,您可以为一些不可读的字符替换换行符
tr'\n'$'\01'
,运行sed,然后使用带有
-z
选项的gnu sed返回
tr$'\01'\n'
,您可以:

sed -z 's@class[[:space:]]\+'"$X"'[[:space:]]\+extends[[:space:]]\+'"$Y"'\([[:space:]{]\)@class '"$X"' extends '"$Z"'\1@g'
测试日期:

请注意,您可以在输入中保留换行符,只需
\([[:space:]\+\)
将它们保存在backreference中,并将引用保存在替换的字符串中

我还添加了对空格或
{
behind
扩展了$Y
类名。正则表达式可能会匹配部分类,例如。您可能希望用
BarModule\u Some
替换某些内容,用
BarModule\u Some\u Other\u类
替换其他内容。因此,
sed
在一个正则表达式中不匹配这两个内容,您需要匹配下一个字符在类名后面加上一个


如果没有gnu sed,您可以为一些不可读的字符替换换行符
tr'\n'$'\01'
,运行sed,然后返回
tr$'\01'\n'

请在问题中添加示例输入和该示例输入所需的输出。
\w
在这里看起来有点奇怪。我对php了解不多,但下划线是arphp名称中也允许使用e。(php,函数名中确实允许使用
\xff
)。要处理换行符,如果使用GNU sed,只需使用
-z
(记住使用
g
全局标志)。是
1.
2.
输入/输出的一部分?根据:\w-匹配任何“单词”字符。一个“单词”字符是任何字母、数字或下划线字符。在这种情况下,名称将只按字母顺序加下划线。老实说,我只会使用Perl。
Perl-I-pE的/../…/”
模拟sed,然后您可以添加
-0777
,使其将整个文件作为一个字符串处理。
-e
是总数与
-E
完全无关(可以使用一个或另一个,也可以同时使用二者)两者都与变量替换无关。wrt
这是一个循环的内部
-循环的目的是什么?请在您的问题中添加示例输入和该示例输入所需的输出。
\w
在这里看起来有点奇怪。我对php不太了解,但php名称中也允许使用下划线。(php,函数名中确实允许使用
\xff
)。要处理换行符,如果使用GNU sed,只需使用
-z
(记住使用
g
全局标志)。是
1.
2.
输入/输出的一部分吗?根据:\w-匹配任何“单词”字符。一个“单词”字符是任何字母、数字或下划线字符。在这种情况下,名称将只按字母顺序加下划线。老实说,我只会使用Perl。
Perl-I-pE的/../…/”
模拟sed,然后您可以添加
-0777
,使其将整个文件作为一个字符串处理。
-e
是总数与
-E
完全无关(可以使用一个或另一个,也可以同时使用二者)而且两者都与变量替换无关。wrt
这是一个循环的内部
-循环的作用是什么?谢谢@kamil cuk。我想这很接近,只是我不知道$X是什么,所以它不会在变量中。我只需要在subs中识别并复制$X部分