¿Cómo dividir una cadena en dos subcadenas de la misma longitud usando bash?


12

Me gustaría dividir una cadena en dos mitades e imprimirlas secuencialmente. Por ejemplo:

abcdef

dentro

abc
def

¿Hay una manera simple de hacerlo o necesita un procesamiento de cadena?


¿Cómo tienes la cadena entrante? ¿Variable? Stdin? ¿Otro?
— Jeff Schaller

1
En una variable Realmente no importa, ya que todo se puede resolver (la entrada estándar se puede poner en una variable).
— Gabriel Diego

Es importante para la eficiencia, especialmente si puede ser posiblemente gigantesco. Y también por conveniencia.
— Peter Cordes

Respuestas:


16

Usando la expansión de parámetros y la aritmética de shell :

La primera mitad de la variable será:

${var:0:${#var}/2}

La segunda mitad de la variable será:

${var:${#var}/2}

para que puedas usar:

printf '%s\n' "${var:0:${#var}/2}" "${var:${#var}/2}"

También puede usar el siguiente comando awk:

awk 'BEGIN{FS=""}{for(i=1;i<=NF/2;i++)printf $i}{printf "\n"}{for(i=NF/2+1;i<=NF;i++){printf $i}{printf "\n"}}'

$ echo abcdef | awk 'BEGIN{FS=""}{for(i=1;i<=NF/2;i++)printf $i}{printf "\n"}{for(i=NF/2+1;i<=NF;i++){printf $i}{printf "\n"}}'
abc
def

¡Gracias por la respuesta!
— Gabriel Diego

Solución concisa y elegante.
— Dudi Boy

3
Puedes deshacerte de la $((...)); La parte offy lenla ${var:off:len}sustitución ya se evalúan como expresiones aritméticas. Ejemplo: foo=01234567; echo "${foo:0:${#foo}/2} ${foo:${#foo}/2}". Eso está documentado, y es lo mismo en zshy ksh93como en bash.
— mosvy

3
Nota: Si la longitud de la cadena es impar, esto aún la dividirá en dos partes, pero la segunda será un carácter más largo.
— peterh - Restablece a Monica

8

Usando split, aquí cadenas y sustitución de comandos:

var=abcdef
printf '%s\n' "$(split -n1/2 <<<$var)" "$(split -n2/2 <<<$var)"

7

Otro awkscript puede ser:

echo abcdef | awk '{print substr($0,1,length/2); print substr($0,length/2+1)}'

1
Tenga en cuenta que no funciona con mawk u busybox awk debido a la ambigüedad de sintaxis de la división /y el /ERE/operador, y el caso especial de ()ser opcional para length(aún esas implementaciones no son compatibles con POSIX en ese caso). Usar length()o length($0)aquí en lugar de lengthayudaría a aquellos. También podría hacer awk 'BEGIN{half = int(length(ARGV[1]) / 2); print substr(ARGV[1], 1, half) ORS substr(ARGV[1], half+1)}' abcdeflo que ahorraría la tubería y el proceso adicional y lo haría funcionar incluso si la cadena contiene caracteres de nueva línea.
— Stéphane Chazelas

1

Python 3

s = input()  # Take one line of input from stdin.
x = len(s) // 2  # Get middle of string. "//" is floor division
print(s[:x], s[x:], sep="\n")  # Print "s" up to "x", then "s" past "x", joined on newlines.

Por ejemplo,

$ echo abcdef | python3 -c 's = input(); x = len(s) // 2; print(s[:x], s[x:], sep="\n")'
abc
def

Si la longitud de la cadena no es un número par, la segunda línea será más larga. P.ej

$ echo abcdefg | python3 -c 's = input(); x= len(s) // 2; print(s[:x], s[x:], sep="\n")'
abc
defg
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.