Come dividere una stringa in due sottostringhe della stessa lunghezza usando bash?


12

Vorrei dividere una stringa in due metà e stamparle in sequenza. Per esempio:

abcdef

in

abc
def

C'è un modo semplice per farlo o ha bisogno di un po 'di elaborazione delle stringhe?


Come hai la stringa in arrivo? Variabile? Stdin? Altro?
Jeff Schaller

1
In una variabile Non importa, poiché tutto può essere risolto (l'input stdin può essere inserito in una variabile).
Gabriel Diego,

È importante per l'efficienza, soprattutto se può essere possibilmente gigantesco. E anche per comodità.
Peter Cordes,

Risposte:


16

Utilizzando l' espansione dei parametri e l' aritmetica della shell :

La prima metà della variabile sarà:

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

La seconda metà della variabile sarà:

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

così puoi usare:

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

Puoi anche usare il seguente 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

Grazie per la risposta!
Gabriel Diego,

soluzione concisa ed elegante.
Dudi Boy,

3
Puoi sbarazzarti di $((...)); la offe lenparte della ${var:off:len}sostituzione sono già valutate come espressioni aritmetiche. Esempio: foo=01234567; echo "${foo:0:${#foo}/2} ${foo:${#foo}/2}". Questo è documentato ed è lo stesso in zshe ksh93in bash.
mosvy,

3
Nota: se la lunghezza della stringa è dispari, questa verrà comunque suddivisa in due parti, ma la seconda sarà un carattere più lungo.
Peter - Ripristina Monica

8

Utilizzando split, qui stringhe e sostituzione comandi:

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

7

Un altro awkscript può essere:

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

1
Si noti che non funziona con mawk o busybox awk a causa dell'ambiguità della sintassi della divisione /e /ERE/dell'operatore e del caso speciale di ()essere facoltativo per length(comunque quelle implementazioni non sono conformi a POSIX in quel caso). Usare length()o length($0)qui invece di lengthsarebbe d'aiuto per quelli. Puoi anche fare awk 'BEGIN{half = int(length(ARGV[1]) / 2); print substr(ARGV[1], 1, half) ORS substr(ARGV[1], half+1)}' abcdefciò che salverà la pipe e il processo extra e lo farà funzionare anche se la stringa contiene caratteri di nuova riga.
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.

Per esempio,

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

Se la lunghezza della stringa non è un numero pari, la seconda riga sarà più lunga. Per esempio

$ echo abcdefg | python3 -c 's = input(); x= len(s) // 2; print(s[:x], s[x:], sep="\n")'
abc
defg
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.