Использование sed для поиска строки с подстановочными знаками, а затем замена на те же подстановочные знаки - PullRequest
0 голосов
/ 20 апреля 2020

Так что я пытаюсь удалить новые строки, используя sed, потому что это единственный способ, которым я могу придумать. Я полностью самоучка, поэтому, возможно, есть более эффективный способ, которого я просто не знаю.

Строка, которую я ищу, это \ HF = - [0-9] (символ новой строки). Проблема в том, что данные, которые они ищут, могут выглядеть следующим образом (Примечание: в этих данных есть реальные символы новой строки, которые, я думаю, вызывают небольшую проблему)

 1\1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536\09-Apr-2020\0\\# 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\1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536\09-Apr-2020\0\\# 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\1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536\09-Apr-2020\0\\# 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\1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536\09-Apr-2020\0\\# 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\1\GINC-N076\SP\RMP2-FC\CC-pVDZ\C12H12\R2536\09-Apr-2020\0\\# 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 и basi c UNIX.

EDIT После попытки

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

мне все еще не повезло избавиться от этих надоедливых символов новой строки.

Если это как-то повлияет на ответы здесь - это остальная часть кода go с одной строкой, вызывающей проблемы

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/\1/' $i &&
    grep '\\HF' $i | awk -F 'HF' '{print substr($2,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

Ответы [ 2 ]

0 голосов
/ 21 апреля 2020

Похоже, ваши строки ввода начинаются с пробела. Я проигнорировал их в этом решении.

sed -rz 's/(AG\\HF=-[0-9]*)\n/\1/g' "$i"
0 голосов
/ 20 апреля 2020

Вот как вы можете исправить свою текущую попытку.

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

Добавьте флаг i, если хотите внести изменения в сам файл, добавьте &&, чтобы отправить работу в фон и др. c. Флаг -E необходим, потому что обратные ссылки (см. Ниже) являются частью расширенных регулярных выражений.

Я внес следующие изменения: я изменил -* на -?, так как должно быть не более одного da sh (если я правильно понимаю, и это на самом деле знак минус, а не да sh). Я добавил точку в выражение в скобках, чтобы десятичная точка тоже соответствовала. (Обратите внимание, что в выражении в скобках точка является регулярным символом). Я обернул все это, за исключением новой строки в скобках - превращая ее в подвыражение , на которое вы можете сослаться с обратной ссылкой - что я и сделал в части замены.

Несколько Примечания, хотя - это объединит строки, даже если все число находится в конце одной строки, но не сопровождается закрытием \. Если на самом деле все число находится в одной строке, а закрывающий \ находится на следующей строке, вы можете слегка изменить команду sed, чтобы оставить их в покое. С другой стороны, это не обрабатывает ситуации, когда, например, одна строка оканчивается на \H, а следующая строка начинается с F=304.222\ Вы только упомянули «разделенное число» в своем заявлении о проблеме; не должны ли вы, тем не менее, также обрабатывать такие случаи, когда символ новой строки разделяет токен \HF=...\, но не в "числовой" части токена?

...