Bagaimana saya bisa menghapus semua teks setelah karakter di bash?

147

Bagaimana saya bisa menghapus semua teks setelah karakter, dalam hal ini titik dua (":"), dalam bash? Bisakah saya menghilangkan usus besar juga? Saya tidak tahu caranya.

Nathan
sumber

Jawaban:

135

Contoh mungkin berguna, tetapi jika saya mengerti Anda dengan benar, ini akan berhasil:

echo "Hello: world" | cut -f1 -d":"

Ini akan mengubah "halo: dunia" menjadi "halo".

Eldad Mor
sumber
5
cutberfungsi, tetapi jawaban saya Dennis lebih baik dan lebih fleksibel. Apakah ada yang tahu jika itu memunculkan proses baru cut?
JoBu1324
3
Lebih baik menggunakan fitur ekspansi parameter bawaan Bash daripada membuat alat yang menjalankan subshell seperti basenamedan cut, lihat jawaban Dennis di bawah ini
Louis Maddox
1
cutdapat membaca dari stdin, jadi itu lebih baik terutama ketika Anda memiliki string yang sangat panjang yang perlu Anda proses, seperti isi file.
Sahas
1
Dan bagaimana ini diterapkan hello: world. Ini setengah jawaban.
K - Keracunan dalam SO tumbuh.
Ini dapat dilakukan dengan menggunakan sintaksis pergantian juga seperti {var /: / ''}, tetapi hanya berfungsi dalam bash ..
Mahesh
265

Di Bash (dan ksh, zsh, dash, dll.), Anda dapat menggunakan ekspansi parameter %yang akan menghapus karakter dari ujung string atau #yang akan menghapus karakter dari awal string. Jika Anda menggunakan satu dari karakter itu, string pencocokan terkecil akan dihapus. Jika Anda menggandakan karakter, yang terpanjang akan dihapus.

$ a='hello:world'
$ b=${a%:*}
$ echo "$b"
hello
$ a='hello:world:of:tomorrow'
$ echo "${a%:*}"
hello:world:of
$ echo "${a%%:*}"
hello
$ echo "${a#*:}"
world:of:tomorrow
$ echo "${a##*:}"
tomorrow
Dijeda sampai pemberitahuan lebih lanjut.
sumber
6
Ini adalah manipulasi string shell asli, jadi tidak ada proses tambahan yang akan muncul. Substitusi Parameter Referensi Bash , Manipulasi String Bash , dan Pembuatan Skrip Bash Lebih Baik
Dodzi Dzakuma
@denniswilliamson Bagaimana saya bisa menghapus 2 karakter setelah string spesifik seperti hello:worldmenjadi hello:wodengan menggunakan ${a%:*}?
3kstc
Jawaban yang bagus, terima kasih banyak, tetapi akan menyenangkan juga menambahkan "${a##*:}"untuk hanya mendapatkan tomorrow=)
avtomaton
1
@openCivilisation: Anda mungkin perlu menggunakan pencocokan ekspresi reguler maka: a='hello:world:of:tomorrow'; pattern=''^([^:]*:).*$'; [[$ a = ~ $ pattern]]; echo "$ {BASH_REMATCH [1]}" `. Itu cocok hanya jika ada titik dua. Jika Anda ingin itu opsional, pola yang berbeda harus digunakan. Penjelasan tentang regex Bash (dan regex secara umum) berada di luar cakupan komentar ini. Anda dapat menemukan pertanyaan lain yang membahas hal ini atau memposting pertanyaan Anda sendiri.
Dijeda sampai pemberitahuan lebih lanjut.
1
@ kp123: Ini adalah contoh pertama dalam jawaban saya. Kali kedua saya tunjukkan (di mana "besok" dihapus), hampir persis situasi yang Anda tanyakan.
Dijeda sampai pemberitahuan lebih lanjut.
9
$ echo 'hello:world:again' |sed 's/:.*//'
hello
sk8asd123
sumber
4
egrep -o '^[^:]*:'
cdhowie
sumber
dapatkah Anda menjelaskan bagaimana menafsirkan ini, Terima kasih.
rɑːdʒɑ
1
egrepGrep dengan -E. Tidak ada bedanya di sini dari biasa grep. -omenginstruksikan grep untuk mencetak hanya bagian dari garis yang cocok dengan ekspresi. ^jangkar pertandingan ke awal baris. [^:]*cocok dengan nol atau lebih karakter yang bukan :karakter. :cocok dengan karakter :.
cdhowie
Terima kasih sekali lagi untuk penjelasannya
r 30dʒɑ
3

Katakanlah Anda memiliki jalur dengan file dalam format ini:

/dirA/dirB/dirC/filename.file

Sekarang Anda hanya menginginkan jalur yang mencakup empat "/". Tipe

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-4 -d"/"

dan output Anda akan menjadi

/dirA/dirB/dirC

Keuntungan menggunakan cut adalah Anda juga dapat memotong direktori uppest serta file (dalam contoh ini), jadi jika Anda mengetik

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-3 -d"/"

output Anda akan menjadi

/dirA/dirB

Meskipun Anda dapat melakukan hal yang sama dari sisi lain dari string, itu tidak masuk akal dalam hal ini sebagai mengetik

$ echo "/dirA/dirB/dirC/filename.file" | cut -f2-4 -d"/"

hasil dalam

dirA/dirB/dirC

Dalam beberapa kasus lain, kasus terakhir mungkin juga bermanfaat. Pikiran bahwa tidak ada "/" di awal output terakhir.

Nico Feulner
sumber
2
Bagaimana jika Anda memiliki direktori "/resources/views/admin/users/relationships/posts.blade.php" dan Anda ingin memotong semuanya setelah kejadian TERAKHIR dari "/", mengingat bahwa Anda TIDAK tahu berapa banyak "/ "karakter ada di string. Jadi di sini saya ingin output menjadi "/ resources / views / admin / users / relations /" (atau bahkan / resources / views / admin / users / hubungan tanpa trailing slash). Bagaimana Anda akan melakukannya?
kp123
-1

potong semuanya setelah contoh terakhir dari ":"

cat fileListingPathsAndFiles.txt | grep -o '^.*:'

dan jika Anda ingin menjatuhkan yang terakhir ":"

cat file.txt | grep -o '^.*:' | sed 's/:$//'

@ kp123: Anda ingin menggantinya :dengan /(di mana seharusnya sed kolon \/)

S Hunter Simpson
sumber