Wie teilt man einen String mit bash in zwei gleich lange Teilstrings?

12

Ich möchte eine Zeichenfolge in zwei Hälften teilen und nacheinander drucken. Beispielsweise:

abcdef

in

abc
def

Gibt es eine einfache Möglichkeit, dies zu tun, oder muss eine Zeichenfolge verarbeitet werden?

Gabriel Diego
quelle
Wie hast du den eingehenden String? Variable? Stdin? Andere?
Jeff Schaller
1
In einer Variablen. Es ist nicht wirklich wichtig, da alles ausgearbeitet werden kann (Standardeingabe kann in eine Variable eingegeben werden).
Gabriel Diego
Es ist wichtig für die Effizienz, besonders wenn es möglicherweise gigantisch sein kann. Und auch der Einfachheit halber.
Peter Cordes

Antworten:

16

Verwendung Parameter Expansion und Shell Arithmetik :

Die erste Hälfte der Variablen ist:

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

Die zweite Hälfte der Variablen ist:

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

so könnten Sie verwenden:

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

Sie können auch den folgenden awk-Befehl verwenden:

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
jesse_b
quelle
Danke für die Antwort!
Gabriel Diego
prägnante und elegante Lösung.
Dudi Boy
3
Sie können das loswerden $((...)); Der offund lenTeil der ${var:off:len}Substitution werden bereits als arithmetische Ausdrücke ausgewertet. Beispiel: foo=01234567; echo "${foo:0:${#foo}/2} ${foo:${#foo}/2}". Das ist dokumentiert und es ist dasselbe in zshund ksh93wie in Bash.
Mosvy
3
Hinweis: Wenn die Länge der Zeichenfolge ungerade ist, wird sie dennoch in zwei Teile geteilt, während der zweite Buchstabe länger ist.
peterh
8

Verwenden Sie splithier Zeichenfolgen und Befehlsersetzung:

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

Ein anderes awkSkript kann sein:

echo abcdef | awk '{print substr($0,1,length/2); print substr($0,length/2+1)}'
Dudi Boy
quelle
1
Beachten Sie, dass es mit mawk oder busybox awk nicht funktioniert, da die Syntax von division /und /ERE/Operator nicht eindeutig ist und der Sonderfall ()optional ist length(in diesem Fall sind diese Implementierungen jedoch nicht POSIX-kompatibel). Verwenden length()oder length($0)hier anstelle von lengthwürde für diejenigen helfen. Sie könnten auch awk 'BEGIN{half = int(length(ARGV[1]) / 2); print substr(ARGV[1], 1, half) ORS substr(ARGV[1], half+1)}' abcdefdie Pipe und den zusätzlichen Prozess speichern und zum Funktionieren bringen, selbst wenn die Zeichenfolge Zeilenumbrüche enthält.
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.

Beispielsweise,

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

Wenn die Zeichenfolge keine gerade Zahl ist, ist die zweite Zeile länger. Z.B

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