Como sed puede variar entre plataformas (en particular, BSD / MacOSX versus Linux), puede ser útil especificar la plataforma en la que está utilizando sed.
Isaac
sed "s / (. *) / # \ 1 /" $ nombre de archivo | tr '#' '\ t'> $ sedTmpFile && mv $ sedTmpFile $ nombre de archivo.
user2432405
Para usuarios de OS X (macOS), consulte esta pregunta .
Ah, sí; para aclarar: no todas las versiones de sed entienden \ten la parte de reemplazo de la expresión (reconoció \ten la parte de coincidencia de patrones muy bien)
John Weldon
3
awwwwwwwwwwwwwwwwwww, está bien, eso es bastante interesante. Y extraño. ¿Por qué harías que lo reconociera en un lugar pero no en el otro ...?
sixtyfootersdude
2
Llamado desde un script, eso no funcionará: sh ignoraría las pestañas. Por ejemplo, el siguiente código de un script de shell agregará $ TEXT_TO_ADD, sin anteponerlo con una tabulación: sed "$ {LINE} a \\ $ TEXT_TO_ADD" $ FILE.
Estabas en el camino correcto con la $'string'pero falta explicación. De hecho, sospecho que debido al uso extremadamente incómodo, probablemente tenga una comprensión incompleta (como la mayoría de nosotros lo hacemos con bash). Vea mi explicación a continuación: stackoverflow.com/a/43190120/117471
Bruno Bronosky
1
Recuerde que BASH no expandirá variables como $TABdentro de comillas simples, por lo que deberá usarlo entre comillas dobles.
nealmcb
Tenga cuidado con el uso de *comillas dobles internas ... esto se tratará como un glob, no como la expresión regular que desea.
levigroker
27
@sedit estaba en el camino correcto, pero es un poco incómodo definir una variable.
Solución (específica de bash)
La forma de hacer esto en bash es poner un signo de dólar delante de su cadena entre comillas.
$ echo -e '1\n2\n3'123
$ echo -e '1\n2\n3'| sed 's/.*/\t&/g'
t1
t2
t3
$ echo -e '1\n2\n3'| sed $'s/.*/\t&/g'123
Si su cadena necesita incluir expansión variable, puede juntar cadenas entre comillas así:
$ timestamp=$(date +%s)
$ echo -e '1\n2\n3'| sed "s/.*/$timestamp"$'\t&/g'149123795811491237958214912379583
Las palabras de la forma $ 'cadena' se tratan especialmente. La palabra se expande a una cadena , y los caracteres de escape con barra invertida se reemplazan según lo especificado por el estándar ANSI C. Las secuencias de escape de barra invertida, si están presentes, se decodifican ...
El resultado expandido es de comillas simples, como si el signo de dólar no hubiera estado presente.
Solución (si debe evitar bash)
Personalmente, creo que la mayoría de los esfuerzos para evitar bash son tontos porque evitar bashisms NO * hace que su código sea portátil. (Su código será menos frágil si lo manipula bash -euque si intenta evitar bash y usa sh[a menos que sea un ninja absoluto de POSIX]). Pero en lugar de tener un argumento religioso al respecto, le daré lo MEJOR * responder.
$ echo -e '1\n2\n3'| sed "s/.*/$(printf '\t')&/g"123
* ¿La mejor respuesta? Sí, porque un ejemplo de lo que la mayoría de los scripters de shell anti-bash harían mal en su código es usarlo echo '\t'como en la respuesta de @ robrecord . Eso funcionará para el eco de GNU, pero no para el eco de BSD. Eso lo explica The Open Group en http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 Y este es un ejemplo de por qué tratar de evitar los bashismos generalmente falla.
Es curioso que estés usando una característica específica de "GNU echo" (interpretando \ t como un carácter de tabulación) para resolver un error específico de "BSD sed" (interpretando \ t como 2 caracteres separados). Presumiblemente, si tiene "GNU echo" también tendrá "GNU sed". En cuyo caso no necesitaría utilizar echo. Con BSD, echo echo '\t'generará 2 caracteres separados. La forma portátil POSIX es usar printf '\t'. Por eso digo: No intente hacer que su código sea portátil sin usar bash. Es más difícil de lo que piensas. Usar bashes lo más portátil que la mayoría de nosotros podemos hacer.
Bruno Bronosky
3
No necesita usar sedpara hacer una sustitución cuando, en realidad, solo desea insertar una pestaña al frente de la línea. La sustitución de este caso es una operación costosa en comparación con simplemente imprimirlo, especialmente cuando se trabaja con archivos grandes. También es más fácil de leer ya que no es regex.
sedno admite \t, ni otras secuencias de escape como \npara el caso. La única forma que encontré para hacerlo fue insertar el carácter de tabulación en el script usando sed.
Dicho esto, es posible que desee considerar el uso de Perl o Python. Aquí hay un breve script de Python que escribí y que uso para todas las expresiones regulares de transmisión:
Creo que otros han aclarado esta adecuadas para determinar otros enfoques ( sed, AWK, etc.). Sin embargo, bashsiguen mis respuestas específicas (probadas en macOS High Sierra y CentOS 6/7).
1) Si OP quisiera usar un método de búsqueda y reemplazo similar al que propusieron originalmente, sugeriría usarlo perlpara esto, de la siguiente manera. Notas: las barras invertidas antes de los paréntesis para expresiones regulares no deberían ser necesarias, y esta línea de código refleja cómo $1es mejor usarla que \1con el perloperador de sustitución (por ejemplo, según la documentación de Perl 5 ).
2) Sin embargo, como lo señaló ghostdog74 , dado que la operación deseada es simplemente agregar una pestaña al comienzo de cada línea antes de cambiar el archivo tmp al archivo de entrada / destino ( $filename), lo recomendaría perlnuevamente pero con la siguiente modificación (s):
3) Por supuesto, el archivo tmp es superfluo , por lo que es mejor hacer todo 'en su lugar' (agregando -ibandera) y simplificar las cosas a una línea más elegante con
Respuestas:
No todas las versiones de
sed
entender\t
. Simplemente inserte una pestaña literal en su lugar (presione Ctrl- Vluego Tab).fuente
\t
en la parte de reemplazo de la expresión (reconoció\t
en la parte de coincidencia de patrones muy bien)Usando Bash, puede insertar un carácter TAB programáticamente así:
fuente
$'string'
pero falta explicación. De hecho, sospecho que debido al uso extremadamente incómodo, probablemente tenga una comprensión incompleta (como la mayoría de nosotros lo hacemos con bash). Vea mi explicación a continuación: stackoverflow.com/a/43190120/117471$TAB
dentro de comillas simples, por lo que deberá usarlo entre comillas dobles.*
comillas dobles internas ... esto se tratará como un glob, no como la expresión regular que desea.@sedit estaba en el camino correcto, pero es un poco incómodo definir una variable.
Solución (específica de bash)
La forma de hacer esto en bash es poner un signo de dólar delante de su cadena entre comillas.
Si su cadena necesita incluir expansión variable, puede juntar cadenas entre comillas así:
Explicación
En bash
$'string'
provoca "expansión ANSI-C". Y eso es lo que la mayoría de nosotros esperamos cuando usamos cosas como\t
,\r
,\n
, etc. Desde: https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-QuotingSolución (si debe evitar bash)
Personalmente, creo que la mayoría de los esfuerzos para evitar bash son tontos porque evitar bashisms NO * hace que su código sea portátil. (Su código será menos frágil si lo manipula
bash -eu
que si intenta evitar bash y usash
[a menos que sea un ninja absoluto de POSIX]). Pero en lugar de tener un argumento religioso al respecto, le daré lo MEJOR * responder.* ¿La mejor respuesta? Sí, porque un ejemplo de lo que la mayoría de los scripters de shell anti-bash harían mal en su código es usarlo
echo '\t'
como en la respuesta de @ robrecord . Eso funcionará para el eco de GNU, pero no para el eco de BSD. Eso lo explica The Open Group en http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 Y este es un ejemplo de por qué tratar de evitar los bashismos generalmente falla.fuente
He usado algo como esto con un shell Bash en Ubuntu 12.04 (LTS):
Para agregar una nueva línea con tabulación, la segunda cuando la primera coincide:
Para reemplazar primero con tabulador, segundo :
fuente
\\t
y no\t
.Utilice
$(echo '\t')
. Necesitará comillas alrededor del patrón.P.ej. Para eliminar una pestaña:
fuente
echo '\t'
generará 2 caracteres separados. La forma portátil POSIX es usarprintf '\t'
. Por eso digo: No intente hacer que su código sea portátil sin usar bash. Es más difícil de lo que piensas. Usarbash
es lo más portátil que la mayoría de nosotros podemos hacer.No necesita usar
sed
para hacer una sustitución cuando, en realidad, solo desea insertar una pestaña al frente de la línea. La sustitución de este caso es una operación costosa en comparación con simplemente imprimirlo, especialmente cuando se trabaja con archivos grandes. También es más fácil de leer ya que no es regex.por ejemplo, usando awk
fuente
Usé esto en Mac:
Usé este enlace como referencia
fuente
sed
no admite\t
, ni otras secuencias de escape como\n
para el caso. La única forma que encontré para hacerlo fue insertar el carácter de tabulación en el script usandosed
.Dicho esto, es posible que desee considerar el uso de Perl o Python. Aquí hay un breve script de Python que escribí y que uso para todas las expresiones regulares de transmisión:
fuente
En lugar de BSD sed, uso perl:
fuente
Creo que otros han aclarado esta adecuadas para determinar otros enfoques (
sed
,AWK
, etc.). Sin embargo,bash
siguen mis respuestas específicas (probadas en macOS High Sierra y CentOS 6/7).1) Si OP quisiera usar un método de búsqueda y reemplazo similar al que propusieron originalmente, sugeriría usarlo
perl
para esto, de la siguiente manera. Notas: las barras invertidas antes de los paréntesis para expresiones regulares no deberían ser necesarias, y esta línea de código refleja cómo$1
es mejor usarla que\1
con elperl
operador de sustitución (por ejemplo, según la documentación de Perl 5 ).2) Sin embargo, como lo señaló ghostdog74 , dado que la operación deseada es simplemente agregar una pestaña al comienzo de cada línea antes de cambiar el archivo tmp al archivo de entrada / destino (
$filename
), lo recomendaríaperl
nuevamente pero con la siguiente modificación (s):3) Por supuesto, el archivo tmp es superfluo , por lo que es mejor hacer todo 'en su lugar' (agregando
-i
bandera) y simplificar las cosas a una línea más elegante confuente