2011-09-06 19 views
109

¿Cómo se usan las líneas de continuación de bash?Líneas de continuación de Bash

que dan cuenta de que usted puede hacer esto:

echo "continuation \ 
lines" 
>continuation lines 

Sin embargo, si ha sangría de código, que no funciona tan bien:

echo "continuation \ 
    lines" 
>continuation  lines 
+4

Guía de estilo de Google Bash Shell [recomienda "aquí" documentos] (https://google.github.io/styleguide/shell.xml # Line_Length_and_Long_Strings) para "Si tiene que escribir cadenas que tienen más de 80 caracteres". Ver la respuesta de [@ tripleee] (http://stackoverflow.com/questions/7316107/bash-continuation-lines/7316685#7316685). –

Respuesta

113

Esto es lo que es posible que desee

$  echo "continuation"\ 
>  "lines" 
continuation lines 

Si esto crea dos argumentos para eco y solo desea uno, entonces veamos la concatenación de cadenas. En bash, la colocación de dos cuerdas junto a la otra concatenar:

$ echo "continuation""lines" 
continuationlines 

Así que una línea de continuación sin un guión es una manera de romper una cadena:

$ echo "continuation"\ 
> "lines" 
continuationlines 

Sin embargo, cuando se utiliza un guión :

$  echo "continuation"\ 
>  "lines" 
continuation lines 

Usted obtiene dos argumentos porque esto ya no es una concatenación.

Si desea una única cadena que cruza líneas, mientras que la sangría pero no conseguir todos esos espacios, uno de los enfoques que puede probar es para deshacerse de las líneas de continuación y el uso de variables:

$ a="continuation" 
$ b="lines" 
$ echo $a$b 
continuationlines 

Esto le permitirá tener un código limpiamente sangrado a expensas de variables adicionales. Si convierte las variables en locales, no debería ser tan malo.

+0

Gracias por su ayuda, pero si bien elimina los espacios, ahora son parámetros separados (Bash interpreta los espacios en la segunda línea como separador de parámetros) y ahora solo se imprimen correctamente debido al comando echo. –

+1

¡Oh, quisieras que una cuerda simple (bash) abarque líneas! Ya lo veo. –

+3

Solución con una variable: 's =" cadena n. ° 1 " s + =" cadena n. ° 2 " s + =" cadena n. ° 3 " eco" $ s "' –

25

Aquí los documentos con el terminador <<-HERE funcionan bien para cadenas de texto de líneas múltiples indentadas. Eliminará las pestañas iniciales del documento aquí.

cat <<-____HERE 
    continuation 
    lines 
____HERE 

Ver también http://ss64.com/bash/syntax-here.html

Si necesita conservar algunos, pero no todos, los espacios iniciales, se usa algo llke

sed 's/^ //' <<____HERE 
    This has four leading spaces. 
    Two of them will be removed by sed. 
____HERE 
-1

Esto probablemente no responde realmente a su pregunta, pero puede que lo encuentres útil de todos modos.

El primer comando crea la secuencia de comandos que se muestra en el segundo comando.

El tercer comando hace que el script sea ejecutable.

El cuarto comando proporciona un ejemplo de uso.

[email protected]:~/tmp/so$ echo $'#!/usr/bin/env python\nimport textwrap, sys\n\ndef bash_dedent(text):\n """Dedent all but the first line in the passed `text`."""\n try:\n  first, rest = text.split("\\n", 1)\n  return "\\n".join([first, textwrap.dedent(rest)])\n except ValueError:\n  return text # single-line string\n\nprint bash_dedent(sys.argv[1])' > bash_dedent 
[email protected]:~/tmp/so$ cat bash_dedent 
#!/usr/bin/env python 
import textwrap, sys 

def bash_dedent(text): 
    """Dedent all but the first line in the passed `text`.""" 
    try: 
     first, rest = text.split("\n", 1) 
     return "\n".join([first, textwrap.dedent(rest)]) 
    except ValueError: 
     return text # single-line string 

print bash_dedent(sys.argv[1]) 
[email protected]:~/tmp/so$ chmod a+x bash_dedent 
[email protected]:~/tmp/so$ echo "$(./bash_dedent "first line 
>  second line 
>  third line")" 
first line 
second line 
third line 

Tenga en cuenta que si usted realmente desea utilizar este script, que tiene más sentido para mover el guión ejecutable en ~/bin por lo que será en su camino.

Consulte la referencia de python para obtener detalles sobre cómo funciona textwrap.dedent.

Si el uso de $'...' o "$(...)" le resulta confuso, haga otra pregunta (una por construcción) si todavía no hay una. Sería bueno proporcionar un enlace a la pregunta que encuentre/solicite para que otras personas tengan una referencia vinculada.

+5

Bien intencionado y posiblemente incluso útil aunque esto puede ser, el OP pidió consejo sobre la sintaxis básica de bash, y usted le dio una definición de función python que usa paradigmas OO, control de flujo excepcional e importaciones. Además, llamaste a un ejecutable como parte de una interpolación de cadenas, algo que una persona que hacía este tipo de preguntas definitivamente no habría visto aún en bash. –

2

Me encontré con una situación en la que tuve que enviar un mensaje largo como parte de un argumento de comando y tuve que cumplir con la limitación de longitud de línea. Los comandos se ve algo como esto:

somecommand --message="I am a long message" args 

La forma en que lo resolvió es mover el mensaje como un documento de aquí (como sugirió @tripleee). Sin embargo, una aquí el documento se convierte en una entrada estándar, por lo que debe ser leído de nuevo, fui con el enfoque de abajo:

message=$(
    tr "\n" " " <<- END 
     This is a 
     long message 
END 
) 
somecommand --message="$message" args 

Esto tiene la ventaja de que $message puede usarse exactamente como la constante de cadena sin espacios en blanco extra o saltos de línea.

Tenga en cuenta que las líneas de mensaje anteriores están precedidas por un carácter tab cada una, que se elimina por el documento aquí mismo (debido al uso de <<-). Todavía hay saltos de línea al final, que luego se reemplazan por dd con espacios.

Tenga en cuenta también que si no elimina las nuevas líneas, aparecerán tal cual cuando se expande "$message". En algunos casos, puede solucionar el problema eliminando las comillas dobles alrededor de $message, pero el mensaje ya no será un único argumento.

-1

However, if you have indented code, it doesn't work out so well:

echo "continuation \ 
    lines" 
>continuation  lines 

intento con comillas simples y la concatenación de las cadenas:

echo 'continuation' \ 
    'lines' 
>continuation lines 

Nota: la concatenación incluye un espacio en blanco.

+1

Funciona con argumentos de eco y cadena, pero no funciona con otras cosas, como la asignación de variables. Aunque la pregunta no era sobre variables, el uso del eco fue solo un ejemplo. En lugar de 'echo' si tuvieras 'x =', obtendrías el error: 'lines: command not found'. –

2

Puede utilizar bash arrays

$ str_array=("continuation" 
      "lines") 

continuación

$ echo "${str_array[*]}" 
continuation lines 

hay un espacio adicional, debido a que (después de manual de bash):

If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS variable

Así que establezca IFS='' para deshacerse de espacio adicional

$ IFS='' 
$ echo "${str_array[*]}" 
continuationlines 
0

Podrías simplemente separarlo con líneas nuevas (sin usar barra diagonal inversa) como se requiere dentro de la sangría de la siguiente manera y solo tiras de líneas nuevas.

Ejemplo:

echo "continuation 
of 
lines" | tr '\n' ' ' 

O si es una variable saltos de línea de definición se convierte automáticamente a espacios. Por lo tanto, tira de espacios adicionales solo si corresponde.

x="continuation 
of multiple 
lines" 
y="red|blue| 
green|yellow" 

echo $x # This will do as the converted space actually is meaningful 
echo $y | tr -d ' ' # Stripping of space may be preferable in this case 
Cuestiones relacionadas