He notado que, si agrego n
a un patrón para sustituir usando sed
, no concuerda. Ejemplo:
$ 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
¿Cómo puedo hacer que esto funcione?
Respuesta aceptada:
En la llamada más simple de sed , tiene uno línea de texto en el espacio del patrón, es decir. 1 línea de n
texto delimitado de la entrada. La única línea en el espacio del patrón no tiene n
… Es por eso que su expresión regular no encuentra nada.
Puede leer varias líneas en el espacio de patrones y manipular las cosas sorprendentemente bien, pero con un esfuerzo más que normal... Sed tiene un conjunto de comandos que permiten este tipo de cosas... Aquí hay un enlace a un resumen de comandos para sed. Es el mejor que he encontrado y me puso en marcha.
Sin embargo, olvide la idea de "una sola línea" una vez que comience a usar los microcomandos de sed. Es útil presentarlo como un programa estructurado hasta que lo sientas... Es sorprendentemente simple e igualmente inusual. Podría considerarlo como el "lenguaje ensamblador" de la edición de texto.
Resumen:Use sed para cosas simples, y tal vez un poco más, pero en general, cuando va más allá de trabajar con una sola línea, la mayoría de las personas prefieren otra cosa...
Dejaré que alguien más sugiera otra cosa... Yo Realmente no estoy seguro de cuál sería la mejor opción (yo usaría sed, pero eso es porque no conozco Perl lo suficientemente bien).
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
Aquí es el mismo guión, condensado en lo que obviamente es más difícil de leer y trabajar, pero algunos llamarían dudosamente una sola línea
sed '/^a test$/{$!{N;s/^a testnPlease do not$/not a testnBe/;ty;P;D;:y}}' alpha.txt
Aquí está mi comando "hoja de trucos"
: # 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