Mengambil karakter [x] pertama untuk string dari pipa

58

Jika saya memiliki output yang sangat panjang dari sebuah perintah (baris tunggal) tetapi saya tahu saya hanya ingin karakter [x] pertama (katakanlah 8) dari output, apa cara termudah untuk mendapatkannya? Tidak ada pembatas.

xenoterracide
sumber
terkait: stackoverflow.com/questions/1405611/...
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

82

Salah satu caranya adalah menggunakan cut:

 command | cut -c1-8

Ini akan memberi Anda 8 karakter pertama dari setiap baris output. Karena cutmerupakan bagian dari POSIX, ia mungkin berada di sebagian besar Unix.

Steven D
sumber
3
Perhatikan bahwa cut -cmemilih karakter; cut -batau head -cmemilih byte. Ini membuat perbedaan di beberapa lokal (dalam praktiknya, ketika menggunakan UTF-8).
Gilles 'SANGAT berhenti menjadi jahat'
Anda juga tidak perlu menentukan indeks awal dalam hal ini. Saying cut -c-8akan memilih dari karakter 1 hingga 8.
Sparhawk
@ Seven, cutsetara dengan Windows?
Pacerier
Juga command | dd bs=8 count=1 2>/dev/null. Tidak mengatakan itu lebih pendek atau lebih tinggi. Alternatif lain.
dubiousjim
@Gilles, tetapi perhatikan bahwa dengan versi GNU saat ini cut, cut -cberfungsi seperti cut -b(yaitu, itu tidak berfungsi dengan baik untuk karakter multi-byte).
Stéphane Chazelas
24

Ini adalah beberapa cara lain untuk mendapatkan hanya 8 karakter pertama.

command | head -c8

command | awk '{print substr($0,1,8);exit}' 

command | sed 's/^\(........\).*/\1/;q'

Dan jika Anda memiliki bash

var=$(command)
echo ${var:0:8}
pengguna1606
sumber
2
Saya pikir perumusan sed berikut ini sedikit lebih mudah dibaca: command | sed 's/\(.\{8\}\).*/\1/'atau jika mendukung sed Anda itu: command | sed -r 's/(.{8}).*/\1/'; Kalau tidak, +1
Steven D
Bagus, tapi perhatikan yang head -cmenghitung byte , bukan karakter. Demikian pula, di antara implementasi Awk utama, hanya awk GNU yang menangani karakter multi-byte dengan benar - FreeBSD Awk dan Mawk tidak.
mklement0
2

Jika Anda memiliki shell yang cukup canggih (misalnya, yang berikut ini akan bekerja di Bash, tidak yakin tentang tanda hubung), Anda dapat melakukannya:

read -n8 -d$'\0' -r <(command)

Setelah dieksekusi read ... <(command), karakter Anda akan berada di variabel shell REPLY. Ketik help readuntuk mempelajari tentang opsi lain.

Penjelasan: -n8argumen untuk readmengatakan bahwa kami ingin hingga 8 karakter. The -d$'\0'mengatakan membaca sampai null, bukan untuk baris baru. Dengan cara ini pembacaan akan berlanjut selama 8 karakter bahkan jika salah satu karakter sebelumnya adalah baris baru (tetapi tidak jika itu nol). Alternatif -n8 -d$'\0'adalah menggunakan -N8, yang bertuliskan tepat 8 karakter atau sampai stdin mencapai EOF. Tidak ada pembatas yang dimuliakan. Itu mungkin lebih sesuai dengan kebutuhan Anda, tetapi saya tidak tahu begitu saja berapa banyak cangkang yang dibaca yang -Nbertentangan dengan penghormatan -ndan -d. Melanjutkan penjelasannya: -rbilang abaikan \-escapes, sehingga, misalnya, kami memperlakukan \\sebagai dua karakter, bukan sebagai tunggal \.

Akhirnya, kami melakukannya read ... <(command)daripada command | read ...karena dalam bentuk kedua, bacaan dijalankan dalam subkulit yang kemudian segera keluar, kehilangan informasi yang baru saja Anda baca.

Pilihan lain adalah melakukan semua pemrosesan Anda di dalam subkulit. Sebagai contoh:

$ echo abcdefghijklm | { read -n8 -d$'\0' -r; printf "REPLY=<%s>\n" "$REPLY"; }
REPLY=<abcdefgh>
dubiousjim
sumber
1
Jika Anda hanya ingin menampilkan 8 karakter, dan tidak perlu memprosesnya dalam shell, maka gunakan saja cut.
dubiousjim
Senang mengetahui tentang read -n <num>; peringatan kecil: Bash 3.x (masih saat ini di OS) keliru menafsirkan <num>sebagai jumlah byte dan dengan demikian gagal dengan karakter multi-byte; ini telah diperbaiki di Bash 4.x.
mklement0
Ini adalah jawaban yang bagus dan bermanfaat. Jauh lebih umum daripada yang lain.
not2qubit
2

Satu lagi solusi liner dengan menggunakan ekspansi parameter

echo ${word:0:x}

EG: word="Hello world"
echo ${word:0:3} or echo ${word::3} 
o/p: Hel


EG.2: word="Hello world"
echo ${word:1:3}
o/p: ell
Prabhat Kumar Singh
sumber
Anda juga bisa menggunakan variabel yang menahan panjangnya, misalnya: x=8; echo ${word:0:$x}alih-alih mengkode integer.
Cometsong
1

Ini portabel:

a="$(command)"             # Get the output of the command.
b="????"                   # as many ? as characters are needed.
echo ${a%"${a#${b}}"}      # select that many chars from $a

Untuk membangun string dengan panjang karakter bervariasi, ada pertanyaan tersendiri di sini .

Komunitas
sumber
0

Saya punya masalah ini ketika secara manual membuat file checksum di repositori maven. Sayangnya cut -cselalu mencetak baris baru di akhir output. Untuk menekan yang saya gunakan xxd:

command | xxd -l$BYTES | xxd -r

Outputnya persis $BYTESbytes, kecuali commandoutputnya lebih pendek, maka outputnya persis seperti itu.

Krzysztof Jabłoński
sumber
metode lain untuk melepas cutbaris baru trailing adalah untuk memasukkannya ke:| tr -d '\n'
Cometsong