Memotong semua karakter setelah yang terakhir /

14

Bagaimana cara saya memotong semua karakter setelah tanda '/' terakhir?

Teks ini

xxxx/x/xx/xx/xxxx/x/yyyyy
xxx/xxxx/xxxxx/yyy

harus kembali

xxxx/x/xx/xx/xxxx/x
xxx/xxxx/xxxxx
Josef Klimuk
sumber
Pertanyaan yang bagus, saya baru sadar bahwa kita tidak memahami pertanyaan itu dengan cara yang sama
Félicien
3
Perintah basenamedan dirnamelakukan ini sudah.
Michael Hampton
Saya tidak berpikir mengedit # 5 untuk pertanyaan itu benar. Menggunakan kata "cut" mungkin ambigu; jika Anda memotong sesuatu, apakah Anda membuang bagian itu, atau apakah Anda hanya menyimpannya? Namun, kata-kata sebelumnya "dan untuk menghilangkan apa yang ada sebelum /" tidak ambigu. Ini diubah menjadi kebalikannya.
egmont
@egmont, kata "cut" sendiri dibawa dari aslinya: "Saya hanya perlu memotong charachters setelah yang terakhir /" menjadi "Bagaimana cara saya memotong semua karakter setelah '/' terakhir?" yang merupakan perubahan frase yang secara wajar menyimpan artinya, IMO. Jika ada, saya merasakan bagian "hilangkan apa itu ..." ambigu: contoh - contohnya sepertinya menyimpan apa yang ada sebelum /. Contohnya, jelaskan.
muru
@uru saya berbicara tentang suntingan yang menambahkan contoh, bukan suntingan Anda.
egmont

Jawaban:

15

Jika Anda ingin mendapatkan "potongan"

yyy
yyyyy

Kamu bisa menggunakan

sed 's|.*/||' 

misalnya.

echo "xxx/xxxx/xxxxx/yyy" | sed 's|.*/||'
echo "xxxx/x/xx/xx/xxxx/x/yyyyy" | sed 's|.*\/||'

keluaran

yyy
yyyyy

(Catatan: Ini menggunakan kemampuan sed untuk menggunakan pemisah selain /, dalam hal ini |, dalam perintah s)


Jika Anda ingin memulai string:

xxx/xxxx/xxxxx
xxxx/x/xx/xx/xxxx/x

Kamu bisa menggunakan

sed 's|\(.*\)/.*|\1|'

misalnya.

echo "xxx/xxxx/xxxxx/yyy" | sed 's|\(.*\)/.*|\1|'
echo "xxxx/x/xx/xx/xxxx/x/yyyyy" | sed 's|\(.*\)/.*|\1|'

keluaran

xxx/xxxx/xxxxx
xxxx/x/xx/xx/xxxx/x
Félicien
sumber
6
Hai, dalam hal ini Anda dapat mengubah pembatas, misalnya, #bukan /. Anda juga dapat menggunakan pilihan -rjika Anda tidak ingin melarikan diri `\` masing-masing karakter khusus: sed -r 's#(^.*)/.*$#\1#'.
pa4080
1
Saya telah mengirimkan usulan pengeditan untuk menggunakan | dari pada /. Jika Anda tidak menyukainya, saya sarankan Anda "tolak dan edit", dan ubah "permulaan" menjadi "awal". (Tolak + Edit, karena dengan cara itu tidak akan disetujui oleh para pembuat persetujuan-robo. Sebagai alternatif, putar kembali perubahan jika sudah disetujui dan Anda tidak menyukainya.)
Martin Bonner mendukung Monica
18

Jika Anda memotong off ujung senar, dirnamemungkin sesuai dengan tagihan:

$ dirname xxxx/x/xx/xx/xxxx/x/yyyyy
xxxx/x/xx/xx/xxxx/x
$ _

Jika Anda mencoba mengisolasi bagian terakhir dari string, gunakan echo /$(basename "$str").

$ str=xxxx/x/xx/xx/xxxx/x/yyyyy
$ echo /$(basename "$str")
/yyyyy
$ _

sumber
3
Sejujurnya, mengapa ada orang yang menyarankan atau menerima jawaban yang melibatkan sed (atau awk, atau metode serupa lainnya) alih-alih hanya menggunakan utilitas yang diinstal dengan OS berada di luar jangkauan saya.
Auspex
@Auspex Saya rasa itu hanya karena dirnamedan basenametidak banyak diketahui, tetapi seddan awkyang.
Volker Siegel
@ Auspex: Karena dirname dan nama bas tidak beroperasi pada stdin, oleh karena itu cat text | basenametidak akan berfungsi. Jadi solusi yang tepat untuk pertanyaan OP menggunakan dirnamedan basenameakan melibatkan xargsdll
Pod
16

Ekspansi parameter dalam bash

Anda dapat menggunakan ekspansi parameter dalam bash, dalam hal ini

  • ${parameter%word}di mana wordadalah/*
  • ${parameter##word}di mana wordadalah*/

Contoh:

Hapus bagian terakhir

$ asdf="xxx/xxxx/xxxxx/yyy"
$ echo ${asdf%/*}
xxx/xxxx/xxxxx

Ini dijelaskan dalam man bash:

${parameter%word}
${parameter%%word}
      Remove matching suffix pattern.  The word is expanded to produce
      a pattern just as in pathname expansion.  If the pattern matches
      a  trailing portion of the expanded value of parameter, then the
      result of the expansion is the expanded value of parameter  with
      the  shortest  matching  pattern (the ``%'' case) or the longest
      matching pattern (the ``%%'' case) deleted.  If parameter  is  @
      or  *,  the  pattern  removal operation is applied to each posi‐
      tional parameter in turn, and the  expansion  is  the  resultant
      list.   If  parameter is an array variable subscripted with @ or
      *, the pattern removal operation is applied to  each  member  of
      the array in turn, and the expansion is the resultant list.

Hapus semua kecuali bagian terakhir

$ asdf="xxx/xxxx/xxxxx/yyy"
$ echo ${asdf##*/}
yyy

Anda dapat menambahkan garis miring seperti itu

$ echo /${asdf##*/}
/yyy

untuk mendapatkan apa yang Anda inginkan pada satu contoh tertentu sesuai dengan pertanyaan yang diedit. Tetapi pertanyaannya telah diedit oleh beberapa orang setelah itu dan tidak mudah untuk mengetahui apa yang Anda inginkan sekarang.

Ini dijelaskan dalam man bash:

${parameter#word}
${parameter##word}
      Remove matching prefix pattern.  The word is expanded to produce
      a pattern just as in pathname expansion.  If the pattern matches
      the  beginning of the value of parameter, then the result of the
      expansion is the expanded value of parameter with  the  shortest
      matching  pattern  (the ``#'' case) or the longest matching pat‐
      tern (the ``##'' case) deleted.  If parameter is  @  or  *,  the
      pattern  removal operation is applied to each positional parame‐
      ter in turn, and the expansion is the resultant list.  If param‐
      eter  is  an array variable subscripted with @ or *, the pattern
      removal operation is applied to each  member  of  the  array  in
      turn, and the expansion is the resultant list.
sudodus
sumber
10

Cara lain adalah menggunakan grephanya menampilkan garis miring terakhir per baris dan apa pun yang mengikutinya:

$ grep -o '/[^/]*$' example.txt
/yyy
/yyyyy

Penjelasan:

-omemberitahu grepuntuk hanya menunjukkan bagian yang cocok dari garis, bukan seluruh baris.

Pola tersebut /[^/]*$cocok dengan garis miring literal /diikuti oleh karakter apa pun kecuali garis miring [^/]berapa kali *hingga akhir baris $.

Komandan Byte
sumber
8

Hanya karena orang lain mengirim lebih banyak jawaban "waras", berikut ini jawaban yang agak konyol:

rev | cut -d/ -f1 | rev

revmembalikkan karakter di setiap baris, misalnya abcd/ef/gmenjadi g/fe/dcba. Kemudian cuthentikan segmen pertama. Akhirnya dibalik lagi.

egmont
sumber
2
Meskipun jawaban ini tidak masuk akal, terutama karena pipa ledeng shell, saya suka jawaban ini :) Terus goyang, +1
Sergiy Kolodyazhnyy
Setuju - tidak waras, tapi badass!
Volker Siegel
3

Solusi klasik dengan awk, yang memperlakukan /sebagai pemisah bidang untuk input dan output dan menetapkan bidang terakhir ke string kosong (yang benar-benar "dereferencing" dari jumlah NFvariabel bidang ):

$ echo "xxx/xxxx/xxxxx/yyy"|awk  'BEGIN{OFS=FS="/"};{$NF="";print $0}'
xxx/xxxx/xxxxx/

Lebih pendek, seperti yang ditunjukkan fedorqui dalam komentar:

$ echo "xxx/xxxx/xxxxx/yyy"|awk  'BEGIN{OFS=FS="/"};NF--'
xxx/xxxx/xxxxx/

Variasi pada hal itu adalah menempatkan path ke dalam awklingkungan eksekusi, yang akan menghemat pada saluran air tetapi membuat awkbagian lebih bertele-tele:

mypath="xxx/xxxx/xxxxx/yyy" awk  'BEGIN{OFS=FS="/"; sub(/\/([^\/]*)$/,"",ENVIRON["mypath"]);print(ENVIRON["mypath"]) };'
Sergiy Kolodyazhnyy
sumber
1
Terlalu bertele-tele, mengapa tidak adil NF--? Dengan cara ini Anda menggunakan printbla bla.
fedorqui
3

Menambah jawaban egmont karena pertanyaannya telah diedit ...

Gunakan --complement jika Anda ingin menghapus bidang pertama dengan -f1 .

echo "xxxx/x/xx/xx/xxxx/x/yyyyy"|rev|cut -d/ -f1 --complement|rev
xxxx/x/xx/xx/xxxx/x

echo "xxxx/x/xx/xx/xxxx/x/yyyyy"|rev|cut -d/ -f1|rev
yyyyy

Juga, pertanyaannya tidak begitu jelas tentang apa yang harus terjadi dengan input yang tidak mengandung garis miring. xxxx => xxxx atau xxxx => tidak ada

Ph3n0x
sumber
Anda dapat menyarankan hasil edit: askubuntu.com/posts/1010356/edit
muru
@muru OP adalah 1 pengguna rep. Bukankah hak istimewa mengedit diberikan pada 2k? askubuntu.com/help/privileges/edit
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy ada yang bisa menyarankan suntingan.
muru
+1 - Saya tidak memperhatikan --complementopsi sebelumnya dan halaman manualnya melingkar. Pelengkap berarti pelengkap. Saya menemukan tutorial memotong yang bagus yang membahasnya di yourownlinux.com/2015/05/... Ini seperti -vdi grep. Beri aku segalanya kecuali apa yang cocok.
Joe
2
-f2-adalah bentuk yang lebih sederhana untuk -f1 --complement.
egmont