Pencocokan regex yang tidak serakah (enggan) di sed?

407

Saya mencoba menggunakan sed untuk membersihkan baris URL untuk mengekstrak domain saja.

Jadi dari:

http://www.suepearson.co.uk/product/174/71/3816/

Saya ingin:

http://www.suepearson.co.uk/

(baik dengan atau tanpa garis miring, tidak masalah)

Saya telah mencoba:

 sed 's|\(http:\/\/.*?\/\).*|\1|'

dan (menghindari quantifier yang tidak rakus)

sed 's|\(http:\/\/.*\?\/\).*|\1|'

tapi sepertinya saya tidak bisa mendapatkan quantifier non-serakah ( ?) untuk bekerja, jadi selalu cocok dengan seluruh string.

Joel
sumber
54
Catatan samping: jika Anda membatasi regex Anda dengan "|", Anda tidak perlu melarikan diri dari "/". Bahkan, sebagian besar orang membatasi dengan "|" bukannya "/" s untuk menghindari "pagar piket".
AttishOculus
12
@AttishOculus Karakter pertama setelah 's' dalam ekspresi pengganti dalam sed adalah pembatas. Oleh karena itu bar ^ foo ^ ^ atau 'foo! Bar! juga bekerja
Squidly
1
Untuk regex yang diperluas, gunakan sed -E 's.... Tetap saja, tidak ada operator yang enggan.
Ondra Žižka
Bukan jawaban untuk judul pertanyaan tetapi dalam kasus khusus ini cut -d'/' -f1-3karya sederhana .
Petr Javorik

Jawaban:

422

Regex Posix / GNU dasar atau diperluas tidak mengakui quantifier yang tidak rakus; Anda perlu regex nanti. Untungnya, Perl regex untuk konteks ini cukup mudah didapat:

perl -pe 's|(http://.*?/).*|\1|'
kekacauan
sumber
13
Untuk melakukannya di tempat gunakan opsi -pi -e.
reallynice
12
Holy smokes Saya tidak percaya itu berhasil :-) Satu-satunya hal yang menyebalkan adalah sekarang skrip saya memiliki ketergantungan pada Perl :-( Di sisi positifnya, hampir setiap distro Linux memiliki Perl sudah jadi mungkin bukan masalah :-)
Freedom_Ben
7
@Freedom_Ben: IIRC perlyang diperlukan oleh POSIX
MestreLion
4
@ dolphus333: "Regex Posix / GNU dasar atau diperluas tidak mengakui quantifier yang tidak rakus" berarti "Anda tidak dapat menggunakan quantifier yang tidak rakus dalam sed".
kekacauan
3
@ Sérgio bagaimana Anda melakukan hal yang diminta, yang tidak mungkin dilakukan sed, menggunakan sintaksis yang pada dasarnya identik dengansed
chaos
251

Dalam kasus khusus ini, Anda bisa menyelesaikan pekerjaan tanpa menggunakan regex yang tidak serakah.

Coba regex non-serakah ini [^/]*alih-alih .*?:

sed 's|\(http://[^/]*/\).*|\1|g'
Gumbo
sumber
3
Bagaimana membuat sed match frase yang tidak serakah menggunakan teknik ini?
user3694243
6
Sayangnya kamu tidak bisa; lihat jawaban chaos .
Daniel H
Terima kasih banyak ... karena perl tidak lagi di basis instalasi default di banyak distro linux!
st0ne
@DanielH Faktanya adalah mungkin untuk mencocokkan frase dengan tidak rakus menggunakan teknik ini seperti yang diminta. Mungkin perlu sedikit rasa sakit untuk menulis pola dengan ketepatan yang cukup. Misalnya saat mem-parsing penetapan nilai-kunci dalam kueri URL yang mungkin diperlukan untuk mencari tugas menggunakan ([^&=#]+)=([^&#]*). Ada kasus-kasus yang tidak bekerja dengan cara ini pasti, misalnya ketika mem-parsing URL untuk bagian inang dan pathname-nya dengan slash akhir dianggap opsional untuk dikecualikan dari penangkapan:^(http:\/\/.+?)/?$
Thomas Urban
121

Dengan sed, saya biasanya menerapkan pencarian non-serakah dengan mencari apa pun kecuali pemisah sampai pemisah:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*\)/.*;\1;p'

Keluaran:

http://www.suon.co.uk

ini adalah:

  • jangan keluar -n
  • mencari, mencocokkan pola, mengganti dan mencetak s/<pattern>/<replace>/p
  • gunakan ;pemisah perintah pencarian alih-alih /untuk membuatnya lebih mudah untuk mengetiknyas;<pattern>;<replace>;p
  • ingat kecocokan antara kurung \(... \), nanti dapat diakses dengan \1, \2...
  • pertandingan http://
  • diikuti oleh apa pun di kurung [], [ab/]berarti baik aatau batau/
  • pertama ^di []berarti not, sehingga diikuti oleh apa pun kecuali hal di[]
  • jadi [^/]artinya apa pun kecuali /karakter
  • *adalah mengulangi grup sebelumnya sehingga [^/]*berarti karakter kecuali /.
  • sejauh ini sed -n 's;\(http://[^/]*\)berarti mencari dan mengingat http://diikuti oleh setiap karakter kecuali /dan ingat apa yang Anda temukan
  • kami ingin mencari sampai akhir domain jadi berhentilah di berikutnya /jadi tambah yang lain /di akhir: sed -n 's;\(http://[^/]*\)/'tetapi kami ingin mencocokkan sisa baris setelah domain jadi tambahkan.*
  • sekarang pertandingan yang diingat dalam grup 1 ( \1) adalah domain, jadi ganti baris yang cocok dengan barang yang disimpan dalam grup \1dan cetak:sed -n 's;\(http://[^/]*\)/.*;\1;p'

Jika Anda juga ingin menyertakan backslash setelah domain, tambahkan satu backslash lagi di grup untuk diingat:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*/\).*;\1;p'

keluaran:

http://www.suon.co.uk/
Stefan
sumber
8
Mengenai pengeditan terbaru: Tanda kurung adalah semacam karakter tanda kurung, jadi tidak salah menyebutnya kurung, terutama jika Anda mengikuti kata dengan karakter yang sebenarnya, seperti yang dilakukan penulis. Juga, ini adalah penggunaan yang disukai dalam beberapa budaya, jadi menggantinya dengan penggunaan yang disukai dalam budaya Anda sendiri tampaknya agak kasar, meskipun saya yakin bukan itu yang dimaksudkan oleh editor. Secara pribadi, saya pikir yang terbaik adalah menggunakan nama deskriptif murni seperti kurung bundar , kurung siku , dan kurung sudut .
Alan Moore
2
Apakah mungkin untuk mengganti pemisah dengan string?
Calculemus
37

sed tidak mendukung operator "tidak rakus".

Anda harus menggunakan operator "[]" untuk mengecualikan "/" dari kecocokan.

sed 's,\(http://[^/]*\)/.*,\1,'

PS tidak perlu backslash "/".

andcoz
sumber
tidak juga. jika pembatas dapat menjadi salah satu dari banyak karakter yang mungkin (katakan saja serangkaian angka), pencocokan negasi Anda mungkin menjadi semakin kompleks. itu baik-baik saja tetapi tentu akan menyenangkan jika memiliki pilihan untuk dibuat. * tidak serakah
gesell
1
Pertanyaannya lebih umum. Solusi ini berfungsi untuk URL tetapi tidak (misalnya) untuk kasus penggunaan saya stripping nol di belakang. s/([[:digit:]]\.[[1-9]]*)0*/\1/jelas tidak akan bekerja dengan baik 1.20300. Karena pertanyaan aslinya adalah tentang URL, maka harus disebutkan dalam jawaban yang diterima.
Daniel H
33

Simulasi quantifier lazy (un-greedy) di sed

Dan semua rasa regex lainnya!

  1. Menemukan kemunculan pertama ekspresi:

    • POSIX ERE (menggunakan -ropsi)

      Regex:

      (EXPRESSION).*|.

      Sed:

      sed -r 's/(EXPRESSION).*|./\1/g' # Global `g` modifier should be on

      Contoh (menemukan urutan angka pertama) Demo langsung :

      $ sed -r 's/([0-9]+).*|./\1/g' <<< 'foo 12 bar 34'
      12

      Bagaimana cara kerjanya ?

      Regex ini mendapat manfaat dari pergantian |. Pada setiap posisi mesin mencoba untuk memilih pertandingan yang paling lama (ini adalah standar POSIX yang diikuti oleh beberapa mesin lain juga) yang artinya berjalan .sampai pertandingan ditemukan ([0-9]+).*. Tetapi ketertiban juga penting.

      masukkan deskripsi gambar di sini

      Karena flag global disetel, engine mencoba untuk melanjutkan pencocokan karakter demi karakter hingga akhir string input atau target kami. Segera setelah kelompok pertama dan satu-satunya menangkap sisi kiri pergantian dicocokkan (EXPRESSION)sisa baris dikonsumsi segera juga .*. Kami sekarang memegang nilai kami di grup penangkapan pertama.

    • POSIX BRE

      Regex:

      \(\(\(EXPRESSION\).*\)*.\)*

      Sed:

      sed 's/\(\(\(EXPRESSION\).*\)*.\)*/\3/'

      Contoh (menemukan urutan angka pertama):

      $ sed 's/\(\(\([0-9]\{1,\}\).*\)*.\)*/\3/' <<< 'foo 12 bar 34'
      12

      Yang ini seperti versi ERE tetapi tanpa pergantian. Itu saja. Pada setiap posisi mesin mencoba untuk mencocokkan angka.

      masukkan deskripsi gambar di sini

      Jika ditemukan, digit berikut lainnya dikonsumsi dan ditangkap dan sisa garis dicocokkan segera jika tidak karena *berarti lebih atau nol melompati kelompok penangkap kedua \(\([0-9]\{1,\}\).*\)*dan tiba pada titik .untuk mencocokkan satu karakter dan proses ini berlanjut.

  2. Menemukan kemunculan pertama ekspresi terbatas :

    Pendekatan ini akan cocok dengan kemunculan pertama string yang dibatasi. Kita bisa menyebutnya blok string.

    sed 's/\(END-DELIMITER-EXPRESSION\).*/\1/; \
         s/\(\(START-DELIMITER-EXPRESSION.*\)*.\)*/\1/g'

    String input:

    foobar start block #1 end barfoo start block #2 end

    -EDE: end

    -SDE: start

    $ sed 's/\(end\).*/\1/; s/\(\(start.*\)*.\)*/\1/g'

    Keluaran:

    start block #1 end

    Regex pertama \(end\).*cocok dan menangkap pembatas ujung pertama enddan mengganti semua cocok dengan karakter yang diambil terakhir yang merupakan pembatas akhir. Pada tahap ini output kami adalah: foobar start block #1 end.

    masukkan deskripsi gambar di sini

    Kemudian hasilnya diteruskan ke regex kedua \(\(start.*\)*.\)*yang sama dengan versi POSIX BRE di atas. Ini cocok dengan satu karakter jika pembatas mulai starttidak cocok jika tidak cocok dan menangkap pembatas mulai dan cocok dengan sisa karakter.

    masukkan deskripsi gambar di sini


Langsung menjawab pertanyaan Anda

Dengan menggunakan pendekatan # 2 (ekspresi terbatas) Anda harus memilih dua ekspresi yang sesuai:

  • EDE: [^:/]\/

  • SDE: http:

Pemakaian:

$ sed 's/\([^:/]\/\).*/\1/g; s/\(\(http:.*\)*.\)*/\1/' <<< 'http://www.suepearson.co.uk/product/174/71/3816/'

Keluaran:

http://www.suepearson.co.uk/

Catatan: ini tidak akan bekerja dengan pembatas identik.

revo
sumber
3) ketika menyarankan situs seperti regex101 untuk demo, harap tambahkan catatan bahwa itu tidak selalu cocok untuk alat cli karena sintaks dan perbedaan fitur
Sundeep
1
@ Tetap Terima kasih. Saya mengubah semua tanda kutip menjadi satu tanda kutip. Juga saya menganggap aturan pertandingan terlama paling kiri yang disebutkan. Namun di seddan semua mesin lainnya mengikuti urutan standar yang sama tidak masalah ketika datang ke kesetaraan. Jadi echo 'foo 1' | sed -r 's/.|([0-9]+).*/\1/g'tidak ada yang cocok tetapi echo 'foo 1' | sed -r 's/([0-9]+).*|./\1/g'tidak.
revo
@ Simpan juga solusi untuk ekspresi terbatas tidak bekerja untuk pembatas awal dan akhir yang identik yang saya tambahkan catatan untuk.
revo
Poin hebat tentang apa yang terjadi ketika berbagai pergantian mulai dari lokasi yang sama dan memiliki panjang yang sama, tebak itu akan mengikuti urutan kiri-kanan seperti mesin lainnya .. perlu mencari ke atas jika dijelaskan dalam manual
Sundeep
ada kasus aneh di sini: stackoverflow.com/questions/59683820/…
Sundeep
20

Solusi non-serakah untuk lebih dari satu karakter

Utas ini benar-benar tua tetapi saya menganggap orang masih membutuhkannya. Katakanlah Anda ingin membunuh segalanya sampai kejadian pertama HELLO. Anda tidak bisa mengatakan [^HELLO]...

Jadi solusi yang bagus melibatkan dua langkah, dengan asumsi bahwa Anda dapat menyimpan kata unik yang tidak Anda harapkan dalam input, katakan top_sekrit.

Dalam hal ini kita dapat:

s/HELLO/top_sekrit/     #will only replace the very first occurrence
s/.*top_sekrit//        #kill everything till end of the first HELLO

Tentu saja, dengan input yang lebih sederhana Anda dapat menggunakan kata yang lebih kecil, atau bahkan mungkin satu karakter.

HTH!

ishahak
sumber
4
Untuk membuatnya lebih baik, berguna dalam situasi di mana Anda tidak dapat mengharapkan karakter yang tidak digunakan: 1. ganti karakter khusus itu dengan KATA yang benar-benar tidak digunakan, 2. ganti urutan akhir dengan karakter khusus, 3. lakukan pencarian yang diakhiri dengan karakter khusus, 4 ganti karakter khusus kembali, 5. ganti kembali WORD khusus. Misalnya, Anda ingin operator serakah antara <hello> dan </hello>:
Jakub
3
Contoh di sini: echo "Temukan: <hello> fir ~ st <br> yes </hello> <hello> sec ~ ond </hello>" | sed -e "s, ~, VERYSPECIAL, g" -e "s, </hello>, ~, g" -e "s,. * Temukan: <hello> ([^ ~] *). *, \ 1 , "-e" s, \ ~, </hello>, "-e" s, VERYSPECIAL, ~, "
Jakub
2
Saya setuju. solusi yang bagus. Saya akan mengulangi komentar menjadi mengatakan: jika Anda tidak dapat mengandalkan ~ tidak digunakan, ganti kejadian saat ini terlebih dahulu menggunakan s / ~ / VERYspeciaL / g, kemudian lakukan trik di atas, lalu kembalikan yang asli ~ menggunakan s / VERYspeciaL / ~ / g
ishahak
1
Saya cenderung suka menggunakan "variabel" yang lebih jarang untuk hal semacam ini, jadi alih-alih `, saya akan menggunakan <$$>(karena $$memperluas ke ID proses Anda di shell, meskipun Anda harus menggunakan tanda kutip ganda daripada tanda kutip tunggal, dan itu mungkin merusak bagian lain dari regex Anda) atau, jika unicode tersedia, sesuatu seperti <∈∋>.
Adam Katz
Pada titik tertentu Anda harus bertanya pada diri sendiri mengapa Anda tidak hanya menggunakan perlatau pythonatau bahasa lain saja. perlmelakukan ini dengan cara yang kurang rapuh dalam satu baris ...
ArtOfWarfare
18

pencocokan sed - non serakah oleh Christoph Sieghart

Trik untuk mendapatkan pencocokan tidak serakah di sed adalah untuk mencocokkan semua karakter tidak termasuk yang mengakhiri pertandingan. Saya tahu, seorang yang tidak punya otak, tetapi saya menghabiskan menit-menit berharga untuk itu dan skrip shell seharusnya, cepat dan mudah. Jadi kalau-kalau ada orang lain yang membutuhkannya:

Pencocokan serakah

% echo "<b>foo</b>bar" | sed 's/<.*>//g'
bar

Pencocokan non serakah

% echo "<b>foo</b>bar" | sed 's/<[^>]*>//g'
foobar
gresolio
sumber
17

Ini dapat dilakukan dengan menggunakan cut:

echo "http://www.suepearson.co.uk/product/174/71/3816/" | cut -d'/' -f1-3
Dee
sumber
9

cara lain, tidak menggunakan regex, adalah dengan menggunakan bidang / metode pembatas mis

string="http://www.suepearson.co.uk/product/174/71/3816/"
echo $string | awk -F"/" '{print $1,$2,$3}' OFS="/"
ghostdog74
sumber
5

sed tentu memiliki tempat tetapi ini bukan salah satu dari mereka!

Seperti yang ditunjukkan Dee: Gunakan saja cut. Jauh lebih sederhana dan jauh lebih aman dalam hal ini. Berikut ini contoh di mana kami mengekstrak berbagai komponen dari URL menggunakan sintaks Bash:

url="http://www.suepearson.co.uk/product/174/71/3816/"

protocol=$(echo "$url" | cut -d':' -f1)
host=$(echo "$url" | cut -d'/' -f3)
urlhost=$(echo "$url" | cut -d'/' -f1-3)
urlpath=$(echo "$url" | cut -d'/' -f4-)

Memberi anda:

protocol = "http"
host = "www.suepearson.co.uk"
urlhost = "http://www.suepearson.co.uk"
urlpath = "product/174/71/3816/"

Seperti yang Anda lihat, ini adalah pendekatan yang jauh lebih fleksibel.

(semua kredit ke Dee)

peterh
sumber
3
sed 's|(http:\/\/[^\/]+\/).*|\1|'
Lucero
sumber
1
Jika Anda menggunakan "|" sebagai pemisah Anda, tidak perlu melarikan diri "/".
Michael Back
3

sed -E mengartikan ekspresi reguler sebagai ekspresi reguler extended (modern)

Pembaruan: -E pada MacOS X, -r di GNU sed.

stepancheg
sumber
4
Tidak itu tidak ... Setidaknya bukan GNU sed.
Michel de Ruiter
7
Lebih luas lagi, -Eini unik untuk BSD seddan karenanya OS X. Tautan ke halaman manual. -rtidak membawa ekspresi reguler yang diperluas ke GNUsed seperti yang tercantum dalam koreksi @ stephancheg. Hati-hati saat menggunakan perintah variabilitas yang dikenal di seluruh distribusi nix. Saya mempelajarinya secara susah-payah.
fny
1
Ini adalah jawaban yang benar jika Anda ingin menggunakan sed, dan merupakan yang paling berlaku untuk pertanyaan awal.
Will Tice
8
-rOpsi GNU sed hanya mengubah aturan pelolosan, sesuai dengan Appendix A Extended regular expressionsfile info dan beberapa tes cepat; itu sebenarnya tidak menambahkan kualifikasi non-serakah ( GNU sed version 4.2.1setidaknya sampai).
eichin
1
GNU sed diakui -Esebagai opsi tidak berdokumen untuk sementara waktu, tetapi dalam rilis 4.2.2.177 , dokumentasi telah diperbarui untuk mencerminkan hal itu, jadi -Etidak masalah untuk keduanya sekarang.
Benjamin W.
3

Masih ada harapan untuk menyelesaikan ini dengan menggunakan pure (GNU) sed. Meskipun ini bukan solusi umum dalam beberapa kasus, Anda dapat menggunakan "loop" untuk menghilangkan semua bagian string yang tidak perlu seperti ini:

sed -r -e ":loop" -e 's|(http://.+)/.*|\1|' -e "t loop"
  • -r: Gunakan regex yang diperluas (untuk + dan tanda kurung tidak dihapus)
  • ": loop": Tentukan label baru bernama "loop"
  • -e: tambahkan perintah ke sed
  • "t loop": Langsung kembali ke label "loop" jika ada penggantian yang berhasil

Satu-satunya masalah di sini adalah ia juga akan memotong karakter pemisah terakhir ('/'), tetapi jika Anda benar-benar membutuhkannya Anda masih dapat dengan mudah memasukkannya kembali setelah "loop" selesai, tambahkan saja perintah tambahan ini di akhir sebelumnya garis komando:

-e "s,$,/,"
mTUX
sumber
2

Karena Anda secara khusus menyatakan sedang mencoba menggunakan sed (alih-alih perl, memotong, dll.), Cobalah mengelompokkan. Ini menghindari pengidentifikasi non-serakah yang berpotensi tidak dikenali. Grup pertama adalah protokol (yaitu 'http: //', 'https: //', 'tcp: //', dll). Grup kedua adalah domain:

echo "http://www.suon.co.uk/product/1/7/3/" | sed "s | ^ \ (. * // \) \ ([^ /] * \). * $ | \ 1 \ 2 |"

Jika Anda tidak terbiasa dengan pengelompokan, mulailah dari sini .

BrianB
sumber
1

Saya menyadari ini adalah entri lama, tetapi seseorang mungkin menganggapnya berguna. Karena nama domain lengkap tidak boleh melebihi total panjang 253 karakter ganti. * Dengan. \ {1, 255 \}

Iain Henderson
sumber
1

Ini adalah cara melakukan pencocokan non-serakah dari string multi-karakter menggunakan sed. Katakanlah Anda ingin mengubah setiap foo...baruntuk <foo...bar>jadi misalnya masukan ini:

$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV

harus menjadi output ini:

ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

Untuk melakukan itu, Anda mengonversi foo dan bilah menjadi karakter individual dan kemudian menggunakan negasi dari karakter tersebut di antara mereka:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

Di atas:

  1. s/@/@A/g; s/{/@B/g; s/}/@C/gmengonversi {dan }ke string placeholder yang tidak dapat ada di input sehingga karakter-karakter tersebut kemudian tersedia untuk dikonversi foodan barke.
  2. s/foo/{/g; s/bar/}/gmengkonversi foodan barke {dan }masing - masing
  3. s/{[^{}]*}/<&>/gsedang melakukan operasi yang kita inginkan - mengonversi foo...barke<foo...bar>
  4. s/}/bar/g; s/{/foo/gmengubah {dan }kembali ke foodan bar.
  5. s/@C/}/g; s/@B/{/g; s/@A/@/g sedang mengonversi string placeholder kembali ke karakter aslinya.

Perhatikan bahwa hal di atas tidak bergantung pada string tertentu yang tidak ada pada input karena string tersebut diproduksi pada langkah pertama, juga tidak peduli kemunculan regexp tertentu yang ingin Anda cocokkan karena Anda dapat menggunakan {[^{}]*}sebanyak yang diperlukan dalam ekspresi untuk mengisolasi kecocokan sebenarnya yang Anda inginkan dan / atau dengan operator pencocokan angka sed, misalnya untuk hanya mengganti kemunculan ke-2:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV
Ed Morton
sumber
1

Belum melihat jawaban ini, jadi inilah cara Anda dapat melakukan ini dengan viatau vim:

vi -c '%s/\(http:\/\/.\{-}\/\).*/\1/ge | wq' file &>/dev/null

Ini menjalankan vi :%ssubstitusi secara global (trailing g), menahan diri untuk tidak meningkatkan kesalahan jika pola tidak ditemukan ( e), kemudian menyimpan perubahan yang dihasilkan ke disk dan berhenti. The &>/dev/nullmencegah GUI dari singkat berkedip pada layar, yang dapat mengganggu.

Saya suka menggunakan vikadang-kadang untuk regex super rumit, karena (1) perl mati sekarat, (2) vim memiliki mesin regex yang sangat canggih, dan (3) Saya sudah akrab dengan regex dalam vipengeditan penggunaan sehari-hari saya dokumen.

Luke Davis
sumber
0
echo "/home/one/two/three/myfile.txt" | sed 's|\(.*\)/.*|\1|'

jangan repot-repot, saya mendapatkannya di forum lain :)

Dee
sumber
4
sehingga Anda mendapatkan pertandingan serakah: /home/one/two/three/, jika Anda menambahkan lain /seperti /home/one/two/three/four/myfile.txtAnda rakus akan cocok fourjuga: /home/one/two/three/four, pertanyaannya adalah tentang non-serakah
stefanB
0

sed 's|\(http:\/\/www\.[a-z.0-9]*\/\).*|\1| bekerja juga

GL2014
sumber
0

Ini adalah sesuatu yang dapat Anda lakukan dengan pendekatan dua langkah dan awk:

A=http://www.suepearson.co.uk/product/174/71/3816/  
echo $A|awk '  
{  
  var=gensub(///,"||",3,$0) ;  
  sub(/\|\|.*/,"",var);  
  print var  
}'  

Keluaran: http://www.suepearson.co.uk

Semoga itu bisa membantu!

VINAY NAIR
sumber
0

Versi sed lainnya:

sed 's|/[:alnum:].*||' file.txt

Ini cocok /diikuti oleh karakter alfanumerik (jadi bukan slash maju lain) serta sisa karakter hingga akhir baris. Setelah itu menggantinya dengan apa-apa (mis. Menghapusnya.)

sycamorex
sumber
1
Saya kira itu seharusnya "[[:alnum:]]", bukan "[:alphanum:]".
oli_arborum