замена определенных строк под строкой, содержащей определенную строку, с использованием редактора sed inplace Linux - PullRequest
1 голос
/ 28 марта 2012

Я пытаюсь выполнить сценарий автоматического ввода файла, который выглядит следующим образом

*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE
$#     cid                                                                 title
$#    ssid      msid     sstyp     mstyp    sboxid    mboxid       spr       mpr
     1         2         3         3         0         0         0         0
$#      fs        fd        dc        vc       vdc    penchk        bt        dt
0.0100          0.000     0.000     0.000     0.000         0     0.000 1.0000E+7
$#     sfs       sfm       sst       mst      sfst      sfmt       fsf       vsf
1.000000  1.000000     0.000     0.000  1.000000  1.000000  1.000000  1.000000
*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE
$#     cid                                                                 title
$#    ssid      msid     sstyp     mstyp    sboxid    mboxid       spr       mpr
     1         3         3         3         0         0         0         0
$#      fs        fd        dc        vc       vdc    penchk        bt        dt
0.0100          0.000     0.000     0.000     0.000         0     0.000 1.0000E+7
$#     sfs       sfm       sst       mst      sfst      sfmt       fsf       vsf
1.000000  1.000000     0.000     0.000  1.000000  1.000000  1.000000  1.000000

Я хочу изменить пятую строку после строки

 *CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE

со строкой из другого файла frictionValues.txt

То, что я использую, выглядит следующим образом

sed -i -e '/^\*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE/{n;n;n;n;n;R frictionValues.txt' -e 'd}' input.txt

, но это изменяет все 5 строк после строки, но 2 раза считывает значения из файла frictionValues.txt. Я хочу, чтобы он читал только первую строку, а затем копировал ее во всех случаях, когда он находит строку. Кто-нибудь может сказать мне, используя sed с редактированием на месте, как этот?

Ответы [ 3 ]

2 голосов
/ 28 марта 2012

Это может сработать для вас (возможно, я не в курсе того, что вы хотите!):

sed '1s|.*|1{x;s/^/&/;x};/^\*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE/{n;n;n;n;n;G;s/.*\\n//}|;q' frictionValues.txt |
sed -i -f - input.txt

Объяснение:

  • Создание сценария sedот первой строки frictionValues.txt, которая вставляет указанную первую строку в пространство удержания (HS).Оставшийся сценарий такой же, как и раньше, но вместо R frictionValues.txt добавляет HS к пространству шаблона, используя G.
  • Запустите указанный выше сценарий sed для файла input.txt, используя -f -, переключитеsed Скрипт передается через stdin из предыдущего конвейера.
2 голосов
/ 28 марта 2012

Попробуйте с этим:

Содержимое frictionValues.txt:

monday 
tuesday

Содержание input.txt будет таким же, как вы вставили в вопрос.

Содержимое script.sed:

## Match literal string.
/^\*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE/ { 

    ## Append next five lines.
    N   
    N   
    N   
    N   
    N   

    ## Delete the last one.
    s/\(^.*\)\n.*$/\1/

    ## Print the rest of lines.
    p   

    ## Queue a line from external file.
    R frictionValues.txt

    ## Read next line (it will the external one).
    b   
}

## Print line.
p

Запустите его как:

sed -nf script.sed input.txt

со следующим результатом:

*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE
$#     cid                                                                 title
$#    ssid      msid     sstyp     mstyp    sboxid    mboxid       spr       mpr
     1         2         3         3         0         0         0         0
$#      fs        fd        dc        vc       vdc    penchk        bt        dt
monday 
$#     sfs       sfm       sst       mst      sfst      sfmt       fsf       vsf
1.000000  1.000000     0.000     0.000  1.000000  1.000000  1.000000  1.000000
*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE
$#     cid                                                                 title
$#    ssid      msid     sstyp     mstyp    sboxid    mboxid       spr       mpr
     1         3         3         3         0         0         0         0
$#      fs        fd        dc        vc       vdc    penchk        bt        dt
tuesday
$#     sfs       sfm       sst       mst      sfst      sfmt       fsf       vsf
1.000000  1.000000     0.000     0.000  1.000000  1.000000  1.000000  1.000000
1 голос
/ 28 марта 2012

Я получил двухэтапный подход: Сначала выясните номер строки, в которой есть соответствующий текст:

linenum=`grep -m 1 \*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE input.txt | awk '{print $1}'`

Теперь объедините команды sed для замены на основе номера строки. Измените данные в linenum + 5 со значением из «frictionValues.txt» - а также удалите данные в linenum + 5

sed -e "$((linenum+5)) c `cat frictionValues.txt`" -e "$((linenum+5)) d" input.txt

Предположения

frictionValues.txt - содержит только одну строку

Вы используете одну из современных ОС Linux

...