Как разбить строку на две подстроки одинаковой длины, используя bash?

12

Я хотел бы разбить строку на две половины и распечатать их последовательно. Например:

abcdef

в

abc
def

Есть ли простой способ сделать это, или он нуждается в обработке строки?

Габриэль Диего
источник
Как у вас есть входящая строка? Переменная? STDIN? Другой?
Джефф Шаллер
1
В переменной. На самом деле это не имеет значения, поскольку все может быть решено (ввод stdin может быть помещен в переменную).
Габриэль Диего
Это важно для эффективности, особенно если это может быть гигантским. А также для удобства.
Питер Кордес

Ответы:

16

Используя расширение параметров и арифметику оболочки :

Первая половина переменной будет:

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

Вторая половина переменной будет:

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

чтобы вы могли использовать:

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

Вы также можете использовать следующую команду 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
jesse_b
источник
Спасибо за ответ!
Габриэль Диего
краткое и элегантное решение.
Dudi Boy
3
Вы можете избавиться от $((...)); offи lenчасть ${var:off:len}замещения уже оценивается как арифметические выражения. Пример: foo=01234567; echo "${foo:0:${#foo}/2} ${foo:${#foo}/2}". Это задокументировано, и это то же самое, что zshи ksh93в bash.
Мосви
3
Примечание. Если длина строки нечетная, она все равно разделится на две части, но вторая будет длиннее символа.
Петер - Восстановить Монику
8

Используя split, здесь строки и подстановку команд:

var=abcdef
printf '%s\n' "$(split -n1/2 <<<$var)" "$(split -n2/2 <<<$var)"
Фредди
источник
7

Другой awkскрипт может быть:

echo abcdef | awk '{print substr($0,1,length/2); print substr($0,length/2+1)}'
Dudi Boy
источник
1
Обратите внимание, что он не работает с mawk или busybox awk из-за синтаксической неоднозначности деления /и /ERE/оператора и особого случая ()необязательности для length(все же эти реализации не являются POSIX-совместимыми в этом случае). Использование length()или length($0)здесь, а lengthне поможет для тех. Вы также можете сделать awk 'BEGIN{half = int(length(ARGV[1]) / 2); print substr(ARGV[1], 1, half) ORS substr(ARGV[1], half+1)}' abcdefчто бы сохранить канал и дополнительный процесс и заставить его работать, даже если строка содержит символы новой строки.
Стефан
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.

Например,

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

Если длина строки не является четным числом, вторая строка будет длиннее. Например

$ echo abcdefg | python3 -c 's = input(); x= len(s) // 2; print(s[:x], s[x:], sep="\n")'
abc
defg
wjandrea
источник