使用 sed 查找带有通配符的字符串,然后用相同的通配符替换

Using sed to find a string with wildcards and then replacing with same wildcards

所以我正在尝试使用 sed 删除新行,因为这是我能想到的唯一方法。我完全是自学的,所以可能有一种我不知道的更有效的方法。

我要搜索的字符串是\HF=-[0-9](换行符)。问题是它正在搜索的数据可能看起来像(注意:此数据中有实际的换行符,我认为这是导致问题的原因)

 1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536-Apr-2020[=10=]\# mp2/cc-
 pVDZ\Squish3_Slide0\0,1\H,0,0.,2.4822,0.\C,0,0.,1.3948,0.\C,0,0.,-1.
 3948,0.\C,0,1.2079,0.6974,0.\C,0,-1.2079,0.6974,0.\C,0,-1.2079,-0.6974
 ,0.\C,0,1.2079,-0.6974,0.\H,0,2.1497,1.2411,0.\H,0,-2.1497,1.2411,0.\H
 ,0,-2.1497,-1.2411,0.\H,0,2.1497,-1.2411,0.\H,0,0.,-2.4822,0.\C,0,0.,1
 .3948,3.\C,0,0.,-1.3948,3.\C,0,1.2079,0.6974,3.\C,0,-1.2079,0.6974,3.\
 C,0,-1.2079,-0.6974,3.\C,0,1.2079,-0.6974,3.\H,0,0.,2.4822,3.\H,0,2.14
 97,1.2411,3.\H,0,-2.1497,1.2411,3.\H,0,-2.1497,-1.2411,3.\H,0,2.1497,-
 1.2411,3.\H,0,0.,-2.4822,3.\Version=ES64L-G09RevD.01\State=1-AG\HF=-4
 61.3998608\MP2=-463.0005321\RMSD=3.490e-09\PG=D02H [SG"(C4H4),X(C8H8)]
 \@

 1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536-Apr-2020[=11=]\# mp2/cc-
 pVDZ\Squish3.1_Slide0\0,1\H,0,0.,2.4822,0.\C,0,0.,1.3948,0.\C,0,0.,-
 1.3948,0.\C,0,1.2079,0.6974,0.\C,0,-1.2079,0.6974,0.\C,0,-1.2079,-0.69
 74,0.\C,0,1.2079,-0.6974,0.\H,0,2.1497,1.2411,0.\H,0,-2.1497,1.2411,0.
 \H,0,-2.1497,-1.2411,0.\H,0,2.1497,-1.2411,0.\H,0,0.,-2.4822,0.\C,0,0.
 ,1.3948,3.1\C,0,0.,-1.3948,3.1\C,0,1.2079,0.6974,3.1\C,0,-1.2079,0.697
 4,3.1\C,0,-1.2079,-0.6974,3.1\C,0,1.2079,-0.6974,3.1\H,0,0.,2.4822,3.1
 \H,0,2.1497,1.2411,3.1\H,0,-2.1497,1.2411,3.1\H,0,-2.1497,-1.2411,3.1\
 H,0,2.1497,-1.2411,3.1\H,0,0.,-2.4822,3.1\Version=ES64L-G09RevD.01\St
 ate=1-AG\HF=-461.4104442\MP2=-463.0062587\RMSD=3.651e-09\PG=D02H [SG"(
 C4H4),X(C8H8)]\@

 1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536-Apr-2020[=12=]\# mp2/cc-
 pVDZ\Squish3.3_Slide1.7\0,1\H,0,0.,2.4822,0.\C,0,0.,1.3948,0.\C,0,0.
 ,-1.3948,0.\C,0,1.2079,0.6974,0.\C,0,-1.2079,0.6974,0.\C,0,-1.2079,-0.
 6974,0.\C,0,1.2079,-0.6974,0.\H,0,2.1497,1.2411,0.\H,0,-2.1497,1.2411,
 0.\H,0,-2.1497,-1.2411,0.\H,0,2.1497,-1.2411,0.\H,0,0.,-2.4822,0.\C,0,
 0.,-0.3052,3.3\C,0,0.,-3.0948,3.3\C,0,1.2079,-1.0026,3.3\C,0,-1.2079,-
 1.0026,3.3\C,0,-1.2079,-2.3974,3.3\C,0,1.2079,-2.3974,3.3\H,0,0.,0.782
 2,3.3\H,0,2.1497,-0.4589,3.3\H,0,-2.1497,-0.4589,3.3\H,0,-2.1497,-2.94
 11,3.3\H,0,2.1497,-2.9411,3.3\H,0,0.,-4.1822,3.3\Version=ES64L-G09Rev
 D.01\State=1-AG\HF=-461.436061\MP2=-463.0177441\RMSD=7.859e-09\PG=C02H
  [SGH(C4H4),X(C8H8)]\@

 1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536-Apr-2020[=13=]\# mp2/cc-
 pVDZ\Squish3.6_Slide0.9\0,1\H,0,0.,2.4822,0.\C,0,0.,1.3948,0.\C,0,0.
 ,-1.3948,0.\C,0,1.2079,0.6974,0.\C,0,-1.2079,0.6974,0.\C,0,-1.2079,-0.
 6974,0.\C,0,1.2079,-0.6974,0.\H,0,2.1497,1.2411,0.\H,0,-2.1497,1.2411,
 0.\H,0,-2.1497,-1.2411,0.\H,0,2.1497,-1.2411,0.\H,0,0.,-2.4822,0.\C,0,
 0.,0.4948,3.6\C,0,0.,-2.2948,3.6\C,0,1.2079,-0.2026,3.6\C,0,-1.2079,-0
 .2026,3.6\C,0,-1.2079,-1.5974,3.6\C,0,1.2079,-1.5974,3.6\H,0,0.,1.5822
 ,3.6\H,0,2.1497,0.3411,3.6\H,0,-2.1497,0.3411,3.6\H,0,-2.1497,-2.1411,
 3.6\H,0,2.1497,-2.1411,3.6\H,0,0.,-3.3822,3.6\Version=ES64L-G09RevD.0
 1\State=1-AG\HF=-461.4376969\MP2=-463.0163868\RMSD=7.263e-09\PG=C02H [
 SGH(C4H4),X(C8H8)]\@

基本上我要找的数字可以根据字符数在任何时候分成两行。我需要去掉分隔数字的换行符,以便我可以将整个值提取到一个单独的文件中。 (我对提取到新文件没有任何问题,因此它不包含在代码中)

目前我正在使用这个代码

sed -i ':a;N;$!ba;s/HF=-*[0-9]*\n/HF=-*[0-9]*/g' $i &&

这几乎有效,期望它不会用相同的值替换通配符值。它用实际文本 [0-9] 代替,并不总是删除换行符。

重要的是输出文件中有实际的新行字符,如果不弄乱我从该输出文件中提取的其他 30 行,就无法更改它。

我想要的是摆脱找到该字符串时出现的换行符,而不管 - 符号和换行符之间有多少位数字。

所以预期的输出会像

 1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536-Apr-2020[=15=]\# mp2/cc-
 pVDZ\Squish3_Slide0\0,1\H,0,0.,2.4822,0.\C,0,0.,1.3948,0.\C,0,0.,-1.
 3948,0.\C,0,1.2079,0.6974,0.\C,0,-1.2079,0.6974,0.\C,0,-1.2079,-0.6974
 ,0.\C,0,1.2079,-0.6974,0.\H,0,2.1497,1.2411,0.\H,0,-2.1497,1.2411,0.\H
 ,0,-2.1497,-1.2411,0.\H,0,2.1497,-1.2411,0.\H,0,0.,-2.4822,0.\C,0,0.,1
 .3948,3.\C,0,0.,-1.3948,3.\C,0,1.2079,0.6974,3.\C,0,-1.2079,0.6974,3.\
 C,0,-1.2079,-0.6974,3.\C,0,1.2079,-0.6974,3.\H,0,0.,2.4822,3.\H,0,2.14
 97,1.2411,3.\H,0,-2.1497,1.2411,3.\H,0,-2.1497,-1.2411,3.\H,0,2.1497,-
 1.2411,3.\H,0,0.,-2.4822,3.\Version=ES64L-G09RevD.01\State=1-AG\HF=-461.3998608\MP2=-463.0005321\RMSD=3.490e-09\PG=D02H [SG"(C4H4),X(C8H8)]
 \@

这些文件比较大,这行代码执行了1500多次,效率越高越好。

此脚本中的所有其他内容都使用了 grep、awk、sed 和基本 UNIX 命令的组合。

编辑 尝试后

    sed -i -E ':a;N;$!ba;s/(\HF=-?[.0-9]*)\n//' $i &&

我仍然没有运气摆脱那些讨厌的换行符。

如果它对答案有任何影响,这里是导致问题的一行代码的其余部分

echo name HF MP2 mpdiff | cat > allE

for i in *.out
    do echo name HF MP2 mpdiff | cat > $i.allE
    grep "Slide" $i | cut -d "\" -f2 | cat | tr -d '\n' > $i.name && 
    grep "EUMP2" $i | cut -d "=" -f3 | cut -c 1-25 | tr '\n' ' ' | tr -s ' ' >> $i.mp && 
    grep "EUMP2" $i | cut -d "=" -f2 | cut -c 1-25 | tr '\n' ' ' | tr -s ' ' >> $i.mpdiff && 
    sed -i -E ':a;N;$!ba;s/(\HF=-?[.0-9]*)\n//' $i &&
    grep '\HF' $i | awk -F 'HF' '{print substr(,2,14)}' | tr '\n' ' ' >> $i.hf && 
    paste $i.name >> $i.energies &&
    sed -i 's/  /0 /g' $i.hf &&
    sed -i 's/\/0/g' $i.hf &&
    sed -i 's/[A-Z]/0/g' $i.hf &&
    paste $i.hf >> $i.energies &&
    sed -i 's/[ABCEFGHIJKLMNOPQRSTUVWXYZ]//g' $i.mp &&
    paste $i.mp >> $i.energies &&
    sed -i 's/[ABCEFGHIJKLMNOPQRSTUVWXYZ]//g' $i.mpdiff &&
    paste $i.mpdiff >> $i.energies &&
    transpose $i.energies >> $i.allE #temp.txt &&
    #cat temp.txt > $i.energies
    #echo $i is finished
done

echo see allE for energies

#rm *.energies #temp.txt
rm *.name
rm *.mp
rm *.hf
rm *.mpdiff

这是解决当前尝试的方法。

sed -E ':a;N;$!ba;s/(\HF=-?[.0-9]*)\n//'

如果要对文件本身进行更改,请添加 i 标志,添加 && 将作业发送到后台,等等。需要 -E 标志,因为反向引用(见下文)是扩展正则表达式的一部分。

我做了以下更改:我将 -* 更改为 -?,因为最多应该有一个破折号(如果我理解正确的话,那实际上是一个减号,而不是破折号) .我在括号表达式中添加了句点,这样小数点也会匹配。 (请注意,在括号表达式中,点是常规字符)。我将除换行符外的所有内容都包裹在括号中 - 使其成为 子表达式 ,您可以使用反向引用来引用它 - 这就是我在替换部分所做的。

但有几点注意事项 - 即使整个数字都在一行的末尾,但后面没有结尾 \,这也会加入行。如果实际上整个数字在一行,但结束 \ 在下一行,您可以稍微更改 sed 命令,让它们保持不变。另一方面,这确实 not 处理这样的情况,例如,一行以 \H 结尾而下一行以 F=304.222\ 开头 你只提到了 "split number" 在你的问题陈述中;但是,您不应该也处理这样的情况吗?换行符拆分了 \HF=...\ 标记,只是不在标记的 "number" 部分?

您的输入行似乎以 space 开头。我在这个解决方案中忽略了它们。

sed -rz 's/(AG\HF=-[0-9]*)\n//g' "$i"