Як розділити рядок на дві підрядки однакової довжини за допомогою bash?


12

Я хотів би розділити рядок на дві половинки і надрукувати їх послідовно. Наприклад:

abcdef

в

abc
def

Чи є простий спосіб це зробити, чи потрібна деяка обробка рядків?


Як у вас є вхідний рядок? Змінна? Стдін? Інший?
Джефф Шаллер

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

Дякуємо за відповідь!
Габріель Дієго

лаконічне та елегантне рішення.
Дуді Хлопчик

3
Ви можете позбутися від $((...)); offі lenчастина ${var:off:len}заміщення вже оцінюється як арифметичні вирази. Приклад: foo=01234567; echo "${foo:0:${#foo}/2} ${foo:${#foo}/2}". Це документально підтверджено, і це те саме, що zshі ksh93в басі.
mosvy

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)}'

1
Зауважте, що він не працює з mawk або busbox 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

Пітон 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.