12

I would like to split a string into two halves and print them sequentially. For example:

abcdef

into

abc
def

Is there a simple way to do it, or it needs some string processing?

  • How do you have the incoming string? Variable? Stdin? Other? – Jeff Schaller May 30 '19 at 21:24
  • 1
    In a variable. It doesn't really matter, as anything can be worked out (stdin input can be put in a variable). – Gabriel Diego May 30 '19 at 21:27
  • It matters for efficiency, especially if it can be possibly-gigantic. And also for convenience. – Peter Cordes May 31 '19 at 10:36
16

Using parameter expansion and shell arithmetic:

The first half of the variable will be:

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

The second half of the variable will be:

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

so you could use:

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

You could also use the following awk command:

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
| improve this answer | |
  • Thanks for the response! – Gabriel Diego May 30 '19 at 21:19
  • concise and elegant solution. – Dudi Boy May 30 '19 at 21:32
  • 3
    You can get rid of the $((...)); the off and len part of the ${var:off:len} substitution are already evaluated as arithmetic expressions. Example: foo=01234567; echo "${foo:0:${#foo}/2} ${foo:${#foo}/2}". That's documented, and it's the same in zsh and ksh93 as in bash. – mosvy May 30 '19 at 21:47
  • 3
    Note: If the length of the string is odd, this will still split it into two parts, but the second will be a character longer. – peterh - Reinstate Monica May 31 '19 at 7:39
8

Using split, here strings and command substitution:

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

Another awk script can be:

echo abcdef | awk '{print substr($0,1,length/2); print substr($0,length/2+1)}'
| improve this answer | |
  • 1
    Note that it doesn't work with mawk or busybox awk because of the syntax ambiguity of division / and the /ERE/ operator, and the special case of () being optional for length (still those implementations are not POSIX compliant in that case). Using length() or length($0) here instead of length would help for those. You could also do awk 'BEGIN{half = int(length(ARGV[1]) / 2); print substr(ARGV[1], 1, half) ORS substr(ARGV[1], half+1)}' abcdef which would save the pipe and extra process and make it work even if the string contains newline characters. – Stéphane Chazelas May 31 '19 at 10:55
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.

For example,

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

If the string length is not an even number, the second line will be longer. E.g.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.