
Quería capturar \n en una variable (supongamos a) y sustituir $a delante del patrón de búsqueda en un archivo (abc.txt)
¿Alguien puede sugerirme la solución?
> cat abc.txt
hi how are you how is your health
> echo $a
\
resultado esperado (patrón de búsqueda - how
)
hi \
how are you \
how is your health
Respuesta1
En un shell tipo Bourne o rc
a='
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt
pasaría una a
variable de entorno que perl
contiene un carácter de nueva línea e perl
insertaría el contenido de esa variable antes de cada aparición de pattern
en el contenido de abc.txt
.
Para asignar cualquier carácter x
que no sea '
una variable en shells tipo Bourne, puede usar:
a='x'
Entonces, para barra invertida:
a='\'
Para nueva línea:
a='
'
Para caracteres de control como nueva línea, pero eso sería aún peor para retroceso o retorno de carro, por ejemplo, eso hace que el código sea menos legible.
ksh93 introdujo una nueva $'...'
forma de comillas para especificar esos caracteres en forma de escape. Otros shells como bash
, zsh
o mksh
FreeBSD sh
lo han copiado y ampliado (como el $'\uXXXX'
formulario agregado por zsh
) desde entonces.
En esos shells, puedes usar:
a=$'\n' a=$'\b' a=$'\r' a=$'\\' a=$'\''
Para asignar una nueva línea, un retroceso, un retorno de carro, una barra invertida o una comilla simple.
Ese operador de cotización aún no es estándar, por lo que no puede usarlo en un sh
script portátil. Una alternativa estándar es utilizar:
a=$(printf '\b')
para retroceso, por ejemplo, pero eso no funciona para nueva línea, ya que la sustitución de comandos ( $(cmd)
) elimina los caracteres de nueva línea finales de la salida de cmd
. Hay que recurrir a trucos como:
nl=$(printf '\n.'); nl=${nl%.}
(es decir, agregue un .
y elimínelo después) para conservarlo.
Ten en cuenta que perl
también entiende esas \n
notaciones en su código, por lo que puedes hacer:
perl -pe 's/pattern/\n$&/g' < abc.txt
La implementación GNU de sed
(y algunas otras hoy en día) también lo admite:
sed 's/pattern/\n&/g' < abc.txt
pero eso no es estándar. Estándar, una nueva línea en la parte de reemplazo del s
comando sed
debe expresarse con una barra invertida seguida de una nueva línea, por lo que sería:
backslash='\' newline='
'
sed "s/pattern/$backslash$newline&/g" < abc.txt
O sin las variables:
sed 's/pattern/\
&/g' < abc.txt
Entonces, si desea insertar una barra invertida y una nueva línea delante de pattern
, necesita:
sed 's/pattern/\\\
&/g' < abc.txt
3 barras invertidas en total, dos para una barra invertida literal y una para la nueva línea. O con perl
:
perl -pe 's/pattern/\\\n$&/g' < abc.txt
O con tu a
variable:
a='\
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt
Respuesta2
También puedes usar los propios comandos de bash usando:
cat abc.txt | sed -e 's/how/\nhow/g' | while read line; do echo "$line \\"; done