Comment diviser une chaîne en deux sous-chaînes de même longueur en utilisant bash?

12

Je voudrais diviser une chaîne en deux moitiés et les imprimer séquentiellement. Par exemple:

abcdef

dans

abc
def

Existe-t-il un moyen simple de le faire ou a-t-il besoin d'un traitement de chaîne?

Gabriel Diego
la source
Comment avez-vous la chaîne entrante? Variable? Stdin? Autre?
Jeff Schaller
1
Dans une variable. Cela n'a pas vraiment d'importance, car tout peut être élaboré (l'entrée stdin peut être placée dans une variable).
Gabriel Diego
C'est important pour l'efficacité, surtout si cela peut être gigantesque. Et aussi pour plus de commodité.
Peter Cordes

Réponses:

16

Utilisation de l' expansion des paramètres et de l' arithmétique du shell :

La première moitié de la variable sera:

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

La seconde moitié de la variable sera:

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

afin que vous puissiez utiliser:

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

Vous pouvez également utiliser la commande awk suivante:

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
la source
Merci pour la réponse!
Gabriel Diego
solution concise et élégante.
Dudi Boy
3
Vous pouvez vous débarrasser de la $((...)); la offet une lenpartie de la ${var:off:len}substitution sont déjà évalués comme des expressions arithmétiques. Exemple: foo=01234567; echo "${foo:0:${#foo}/2} ${foo:${#foo}/2}". C'est documenté, et c'est la même chose dans zshet ksh93comme dans bash.
mosvy
3
Remarque: Si la longueur de la chaîne est impaire, cela la divisera toujours en deux parties, mais la seconde sera un caractère plus long.
peterh
8

En utilisant split, ici les chaînes et la substitution de commandes:

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

Un autre awkscript peut être:

echo abcdef | awk '{print substr($0,1,length/2); print substr($0,length/2+1)}'
Dudi Boy
la source
1
Notez qu'il ne fonctionne pas avec mawk ou busybox awk en raison de l'ambiguïté de la syntaxe de la division /et de l' /ERE/opérateur, et du cas particulier d' ()être facultatif pour length(toujours ces implémentations ne sont pas conformes POSIX dans ce cas). Utiliser length()ou length($0)ici au lieu de lengthserait utile pour ceux-ci. Vous pouvez également faire awk 'BEGIN{half = int(length(ARGV[1]) / 2); print substr(ARGV[1], 1, half) ORS substr(ARGV[1], half+1)}' abcdefce qui sauverait le canal et le processus supplémentaire et le ferait fonctionner même si la chaîne contient des caractères de nouvelle ligne.
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.

Par exemple,

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

Si la longueur de la chaîne n'est pas un nombre pair, la deuxième ligne sera plus longue. Par exemple

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