Gunakan spasi sebagai pembatas dengan perintah cut

328

Saya ingin menggunakan spasi sebagai pembatas dengan cutperintah.

Sintaks apa yang dapat saya gunakan untuk ini?

Jaelebi
sumber
42
tidak benar, halaman manual untuk cut tidak menjelaskan hal ini dan, secara umum, tidak informatif
UncleZeiv
2
Juga, "info cut" tidak ada perbaikan dalam kasus ini.
Pria luar angkasa cardiff
3
@ mklement0 jika saya ingat, saya membalas komentar yang telah dihapus, yang menolak pertanyaan ini karena dijawab di halaman manual, yang menurut pendapat saya "tidak benar", terlepas dari ada alasan yang baik untuk itu atau tidak - sekarang, sementara saya mengakui bahwa mungkin ada alasan yang baik untuk kurangnya informasi ini, saya masih berpikir bahwa dokumentasi tanpa contoh penggunaan umum sering setidaknya menjengkelkan, ketika tidak langsung sia
UncleZeiv
3
@UncleZeiv Mengerti; terima kasih telah mengklarifikasi; mengingat minat pada pertanyaan ini, wajar untuk menganggap bahwa manhalaman tersebut tidak cukup. Mari kita lihat: " -d delimGunakan delimsebagai karakter pembatas bidang alih-alih karakter tab." (BSD cut, tetapi versi GNU dan spesifikasi POSIX menyatakan hampir sama). Menggunakan shell untuk memohon cut- kasus yang khas - karena itu mengharuskan Anda untuk tahu bagaimana umumnya melewati ruang sebagai argumen menggunakan sintaks shell , yang ini bisa dibilang bukan cutpekerjaan manusia halaman. Contoh dunia nyata selalu membantu, dan halaman manual GNU tidak memilikinya.
mklement0
4
meskipun jawaban yang dipilih secara teknis benar, pertimbangkan untuk memilih jawaban yang lebih baru dan komprehensif oleh @ mklement0 sebagai jawaban kanonik sehingga ia memfilter ke atas.
David LeBauer

Jawaban:

367
cut -d ' ' -f 2

Di mana 2 adalah nomor bidang dari bidang batas-ruang yang Anda inginkan.

RichieHindle
sumber
2
dapatkah Anda memberi tahu cut untuk menggunakan sejumlah karakter tertentu sebagai pembatas, seperti di RegEx? mis. sejumlah spasi, mis. +
amfibi
3
@foampile Tidak, saya tidak yakin Anda bisa.
Jonathan Hartley
6
Anda tidak dapat menggunakan regex dengan cut, tetapi Anda dapat dengan cutsyang mencoba untuk "memperbaiki" semua cutbatasan: github.com/arielf/cuts
arielf
Anda bisa mendapatkan setiap bidang ruang-dibatasi ketiga? suka cut -d ' ' -f 3,6,9,12,15,18tanpa harus menentukan setiap angka?
Monocito
169

Biasanya jika Anda menggunakan spasi sebagai pembatas, Anda ingin memperlakukan beberapa spasi sebagai satu, karena Anda mem-parsing output dari sebuah perintah yang menyelaraskan beberapa kolom dengan spasi. (dan pencarian google untuk itu menuntun saya ke sini)

Dalam hal ini satu cutperintah tidak cukup, dan Anda perlu menggunakan:

tr -s ' ' | cut -d ' ' -f 2

Atau

awk '{print $2}'
BeniBela
sumber
2
Terima kasih atas penggunaan contoh awk, hanya apa yang saya butuhkan.
spazm
44

Untuk melengkapi jawaban yang ada dan bermanfaat; ujung topi untuk Dukungan QZ karena mendorong saya untuk mengirim jawaban terpisah:

Dua mekanisme berbeda berperan di sini:

  • (A) apakah cut itu sendiri memerlukan pembatas (ruang, dalam hal ini) diteruskan ke -dopsi untuk menjadi argumen yang terpisah atau apakah dapat diterima untuk menambahkannya langsung ke -d.

  • (B) bagaimana shell umumnya mem-parsing argumen sebelum meneruskannya ke perintah yang dipanggil.

(a) dijawab dengan kutipan dari pedoman POSIX untuk utilitas (penekanan milik saya)

Jika SYNOPSIS dari utilitas standar menunjukkan opsi dengan argumen opsi wajib [...] aplikasi yang sesuai harus menggunakan argumen terpisah untuk opsi itu dan argumen opsi-nya . Namun , implementasi yang sesuai juga akan mengizinkan aplikasi untuk menentukan opsi dan opsi-argumen dalam string argumen yang sama tanpa karakter intervensi .

Dengan kata lain: Dalam hal ini, karena -dopsi-argumen wajib , Anda dapat memilih apakah akan menentukan pembatas sebagai :

  • (s) BAIK: argumen terpisah
  • (d) OR: sebagai nilai langsung terpasang ke-d .

Setelah Anda memilih (d) atau (d), shell -string parsing literal - (b) - yang penting:

  • Dengan pendekatan (s) , semua bentuk berikut SETARA:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • Dengan pendekatan (d) , semua bentuk berikut ini EQUIVALENT:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

Kesetaraan dijelaskan oleh pemrosesan string-literal shell :

Semua solusi di atas menghasilkan string yang sama persis (di setiap kelompok) saat cutmelihatnya :

  • (s) : cutmelihat -d, sebagai argumennya sendiri , diikuti oleh argumen terpisah yang berisi karakter spasi - tanpa tanda kutip atau \awalan !.

  • (D) : cutmelihat -d plus char spasi - tanpa tanda kutip atau \awalan! - sebagai bagian dari argumen yang sama .

Alasan bentuk-bentuk pada kelompok masing-masing pada akhirnya identik dua kali lipat, berdasarkan pada bagaimana shell mem-parsing string literal :

  • Shell memungkinkan literal untuk ditentukan sebagaimana adanya melalui mekanisme yang disebut mengutip , yang dapat mengambil beberapa bentuk :
    • string yang dikutip tunggal : konten di dalamnya '...'diambil secara harfiah dan membentuk argumen tunggal
    • string dikutip ganda : isi di dalamnya "..."juga membentuk argumen tunggal , tetapi tunduk pada interpolasi (memperluas referensi variabel seperti $var, penggantian perintah ( $(...)atau `...`), atau ekspansi aritmatika ( $(( ... ))).
    • \-kutipan karakter individu : a \mendahului karakter tunggal menyebabkan karakter yang akan ditafsirkan sebagai literal.
  • Mengutip dilengkapi dengan penghapusan kutipan , yang berarti bahwa begitu shell telah mem-parsing baris perintah, itu menghilangkan karakter kutipan dari argumen (melampirkan '...'atau "..."atau \contoh) - dengan demikian, perintah yang dipanggil tidak pernah melihat karakter kutipan .
mklement0
sumber
36

Anda juga bisa mengatakan:

cut -d\  -f 2

Perhatikan bahwa ada dua spasi setelah garis miring terbalik.

Chas. Owens
sumber
30
Orang yang tahu bahwa '\' lolos dari karakter berikutnya akan sangat berhati-hati untuk mencatat apa yang terjadi selanjutnya. Menggunakan '\' untuk keluar dari karakter luar angkasa seperti ini adalah ungkapan yang sangat umum.
Jonathan Hartley
3
@ Jonathan Hartley umumnya sebagian besar kode memang tidak dapat dibaca :)
Luca Borrione
1
Dari perspektif linux / unix, \ adalah upaya pertama saya dan berhasil. Saya setuju itu kurang jelas jika dibandingkan dengan ' ', tapi saya yakin banyak yang senang membacanya di sini sebagai jaminan perilaku. Untuk pemahaman yang lebih baik, silakan lihat komentar @ mklement0 di bawah ini.
tresf
Koreksi @JonathanHartley: "orang yang egois yang tahu bahwa 'lolos dari karakter berikutnya dan menganggap semua orang tahu itu juga". Untuk proyek pribadi ini tidak berlaku, tetapi dalam pengaturan tim, asumsi itu sangat berbahaya (dan berpotensi mahal).
Eduard Nicodei
1
@EduardNicodei Oh saya setuju. Kami berbicara tentang pembaca kode ("siapa yang memperhatikan ...?"), Bukan penulis. Tetapi juga, pada beberapa tim tidak masalah untuk mengasumsikan tingkat kemahiran tertentu. Tergantung pada lingkungan.
Jonathan Hartley
5

Saya baru saja menemukan bahwa Anda juga dapat menggunakan "-d ":

cut "-d "

Uji

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am
fedorqui 'SO berhenti merugikan'
sumber
1
Memang - atau '-d '.
mklement0
3
Catat itu dari cutsudut pandang 's semua berikut ini adalah identik: "-d ", '-d ', -d" ", -d' ', dan -d\<space>: semua bentuk langsung append pilihan argumen (spasi) ke pilihan ( -d) dan hasilnya dalam string yang sama persis pada saat cutmelihat mereka: satu argumen yang berisi d diikuti oleh spasi, setelah shell melakukan penghapusan kutipan
mklement0
1
@ jawaban mklement0 ini harus yang jawabannya. Ini adalah yang paling komprehensif di halaman ini (meskipun itu adalah komentar).
tresf
@QZSupport: Saya menghargai sentimen dan dorongan - ini telah menginspirasi saya untuk mengirim jawaban saya sendiri dengan informasi latar belakang tambahan.
mklement0
1
Penemuan Lol yang menakjubkan!
Harry
4

Anda tidak dapat melakukannya dengan mudah dengan memotong jika data memiliki misalnya beberapa ruang. Saya merasa bermanfaat untuk menormalkan input agar lebih mudah diproses. Salah satu triknya adalah menggunakan sed untuk normalisasi seperti di bawah ini.

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar
Anssi
sumber
3

scut , utilitas cut-like (lebih pintar tapi lebih lambat saya buat) yang dapat menggunakan perl regex sebagai token melanggar. Breaking di whitespace adalah default, tetapi Anda juga dapat break pada regex multi-char, regex alternatif, dll.

scut -f='6 2 8 7' < input.file  > output.file

jadi perintah di atas akan memecah kolom pada spasi putih dan mengekstrak (berbasis 0) cols 6 2 8 7 dalam urutan itu.

Harry Mangalam
sumber
0

Saya punya jawaban (saya akui jawaban yang agak membingungkan) yang melibatkan sed, ekspresi reguler dan grup tangkap:

  • \S* - kata pertama
  • \s* - pembatas
  • (\S*) - kata kedua - ditangkap
  • .* - sisa baris

Sebagai sedekspresi, grup penangkap perlu melarikan diri, yaitu \(dan\) .

The \1pengembalian salinan kelompok ditangkap, yaitu kata kedua.

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

Ketika Anda melihat jawaban ini, itu agak membingungkan, dan, Anda mungkin berpikir, mengapa repot-repot? Yah, aku berharap bahwa beberapa, mungkin pergi "Aha!" dan akan menggunakan pola ini untuk menyelesaikan beberapa masalah ekstraksi teks yang kompleks dengan satu sedekspresi.

Stephen Quan
sumber