Bagaimana cara membagi string menjadi dua substring dengan panjang yang sama menggunakan bash?

12

Saya ingin membagi string menjadi dua bagian dan mencetaknya secara berurutan. Sebagai contoh:

abcdef

ke

abc
def

Apakah ada cara sederhana untuk melakukannya, atau perlu beberapa pemrosesan string?

Gabriel Diego
sumber
Bagaimana Anda memiliki string yang masuk? Variabel? Stdin? Lain?
Jeff Schaller
1
Dalam sebuah variabel. Tidak masalah, karena apa pun dapat dikerjakan (input stdin dapat dimasukkan ke dalam variabel).
Gabriel Diego
Itu penting untuk efisiensi, terutama jika itu bisa jadi sangat besar. Dan juga untuk kenyamanan.
Peter Cordes

Jawaban:

16

Menggunakan ekspansi parameter dan aritmatika shell :

Paruh pertama dari variabel tersebut adalah:

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

Paruh kedua variabel adalah:

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

jadi kamu bisa menggunakan:

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

Anda juga bisa menggunakan perintah awk berikut:

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
sumber
Terima kasih atas tanggapannya!
Gabriel Diego
solusi ringkas dan elegan.
Dudi Boy
3
Anda dapat menyingkirkan $((...)); yang offdan lenbagian dari ${var:off:len}substitusi sudah dievaluasi sebagai ekspresi aritmatika. Contoh: foo=01234567; echo "${foo:0:${#foo}/2} ${foo:${#foo}/2}". Itu didokumentasikan, dan itu sama di zshdan ksh93seperti di bash.
Mosvy
3
Catatan: Jika panjang string aneh, ini masih akan membaginya menjadi dua bagian, tetapi yang kedua akan menjadi karakter yang lebih panjang.
peterh
8

Menggunakan split, di sini string dan substitusi perintah:

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

awkSkrip lain dapat berupa:

echo abcdef | awk '{print substr($0,1,length/2); print substr($0,length/2+1)}'
Boy Dudi
sumber
1
Perhatikan bahwa itu tidak bekerja dengan mawk atau busybox awk karena ambiguitas sintaksis dari divisi /dan /ERE/operator, dan kasus khusus ()sebagai opsional untuk length(masih implementasi yang tidak sesuai dengan POSIX dalam kasus itu). Menggunakan length()atau di length($0)sini bukannya lengthakan membantu mereka. Anda juga bisa melakukan awk 'BEGIN{half = int(length(ARGV[1]) / 2); print substr(ARGV[1], 1, half) ORS substr(ARGV[1], half+1)}' abcdefyang akan menyimpan pipa dan proses tambahan dan membuatnya berfungsi bahkan jika string tersebut mengandung karakter baris baru.
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.

Sebagai contoh,

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

Jika panjang string bukan angka genap, baris kedua akan lebih panjang. Misalnya

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