GNU/Linux >> Znalost Linux >  >> Linux

Jak použít Sed k výměně víceřádkového řetězce?

Všiml jsem si toho, když přidám n na vzor pro nahrazení pomocí sed , to se neshoduje. Příklad:

$ cat > alpha.txt
This is
a test
Please do not
be alarmed

$ sed -i'.original' 's/a testnPlease do not/not a testnBe/' alpha.txt

$ diff alpha.txt{,.original}

$ # No differences printed out

Jak to mohu zprovoznit?

Přijatá odpověď:

V nejjednodušším volání sed , má jeden řádek textu ve vzorovém prostoru, tzn. 1 řádek z n text oddělený od vstupu. Jediný řádek v prostoru vzoru nemá n … Proto váš regulární výraz nic nenachází.

Můžete číst více řádků do prostoru vzorů a manipulovat s věcmi překvapivě dobře, ale s větším úsilím, než je obvyklé.. Sed má sadu příkazů, které umožňují tento typ věcí... Zde je odkaz na Souhrn příkazů pro sed. Je to nejlepší, co jsem našel, a dostal mě do pohybu.

Jakmile však začnete používat mikropříkazy sed, zapomeňte na myšlenku „one-liner“. Je užitečné si to rozložit jako strukturovaný program, dokud to neucítíte... Je to překvapivě jednoduché a stejně neobvyklé. Dalo by se to považovat za „jazyk sestavy“ úprav textu.

Shrnutí:Používejte sed na jednoduché věci a možná trochu víc, ale obecně platí, že když to přesáhne práci s jedním řádkem, většina lidí dává přednost něčemu jinému...
Nechám někoho jiného, ​​aby navrhl něco jiného.. I Opravdu si nejsem jistý, jaká by byla nejlepší volba (použil bych sed, ale to je proto, že neznám dost dobře perl.)

sed '/^a test$/{
       $!{ N        # append the next line when not on the last line
         s/^a testnPlease do not$/not a testnBe/
                    # now test for a successful substitution, otherwise
                    #+  unpaired "a test" lines would be mis-handled
         t sub-yes  # branch_on_substitute (goto label :sub-yes)
         :sub-not   # a label (not essential; here to self document)
                    # if no substituion, print only the first line
         P          # pattern_first_line_print
         D          # pattern_ltrunc(line+nl)_top/cycle
         :sub-yes   # a label (the goto target of the 't' branch)
                    # fall through to final auto-pattern_print (2 lines)
       }    
     }' alpha.txt  

Zde je to stejný scénář, zhuštěný do toho, co je zjevně těžší na čtení a práci s ním, ale někteří by pochybně nazvali jednořádkovou

sed '/^a test$/{$!{N;s/^a testnPlease do not$/not a testnBe/;ty;P;D;:y}}' alpha.txt

Zde je můj příkaz „cheat-sheet“

:  # label
=  # line_number
a  # append_text_to_stdout_after_flush
b  # branch_unconditional             
c  # range_change                     
d  # pattern_delete_top/cycle          
D  # pattern_ltrunc(line+nl)_top/cycle 
g  # pattern=hold                      
G  # pattern+=nl+hold                  
h  # hold=pattern                      
H  # hold+=nl+pattern                  
i  # insert_text_to_stdout_now         
l  # pattern_list                       
n  # pattern_flush=nextline_continue   
N  # pattern+=nl+nextline              
p  # pattern_print                     
P  # pattern_first_line_print          
q  # flush_quit                        
r  # append_file_to_stdout_after_flush 
s  # substitute                                          
t  # branch_on_substitute              
w  # append_pattern_to_file_now         
x  # swap_pattern_and_hold             
y  # transform_chars                   

Linux
  1. Použijte příkaz SED k vyhledání a nahrazení řetězce v souborech – Jak provést tento úkol na Ubuntu?

  2. Jak nahradit řetězec v souboru (souborech)?

  3. Použít Sed k nahrazení řetězce řetězcem obsahujícím název adresáře (tj. lomítko „/“)?

  1. Jak použít sed k nahrazení proměnné konfiguračního souboru?

  2. Multi-Line Sed Vyměnit

  3. Jak rekurzivně nahradit znaky sed?

  1. Jak nahradit řetězec řetězcem obsahujícím lomítko se Sed?

  2. Jak použít Sed nebo Ex k nahrazení bloku (víceřádkového kódu) novým blokem textu (kódu)?

  3. Použití grep a sed k nalezení a nahrazení řetězce