Bagaimana cara mengekstrak teks dari string menggunakan sed?


98

Contoh string saya adalah sebagai berikut:

This is 02G05 a test string 20-Jul-2012

Sekarang dari string di atas saya ingin mengekstrak 02G05. Untuk itu saya mencoba regex berikut dengan sed

$ echo "This is 02G05 a test string 20-Jul-2012" | sed -n '/\d+G\d+/p'

Tetapi perintah di atas tidak mencetak apa pun dan alasan saya yakin adalah tidak dapat mencocokkan apa pun dengan pola yang saya berikan ke sed.

Jadi, pertanyaan saya adalah apa yang saya lakukan salah di sini dan bagaimana memperbaikinya.

Ketika saya mencoba string dan pola di atas dengan python, saya mendapatkan hasil saya

>>> re.findall(r'\d+G\d+',st)
['02G05']
>>>

6
Python jelas tidak sed. Rasa regex mereka sangat berbeda.
tripleee

Jawaban:


95

Polanya \dmungkin tidak didukung oleh Anda sed. Coba [0-9]atau [[:digit:]]sebagai gantinya.

Untuk hanya mencetak pertandingan yang sebenarnya (bukan seluruh baris yang cocok), gunakan substitusi.

sed -n 's/.*\([0-9][0-9]*G[0-9][0-9]*\).*/\1/p'

6
Terima kasih itu bekerja dengan baik. Tapi saya punya pertanyaan mengapa .*perlu dengan regex Anda karena ketika saya mencobanya sed -n 's/\([0-9]\+G[0-9]\+\)/\1/p'hanya mencetak seluruh baris.
RanRag

7
Itu sebabnya, bukan? Ganti apa pun yang muncul sebelum dan sesudah pertandingan dengan norhing, lalu cetak seluruh baris.
tripleee

1
@tripleee Ini hanya mencetak 2G05tidak 02G05. Ekspresi yang berhasil adalah's/.*\([0-9][0-9]G[0-9][0-9]*\).*/\1/p'
Kshitiz Sharma

1
Itu mengkodekannya menjadi tepat dua digit. Sesuatu seperti sed -n 's/\(.*[^0-9]\)\?\([0-9][0-9]*G[0-9][0-9]*\).*/\2/p'itu lebih umum. (Saya berasumsi seddukungan Anda \?untuk nol atau satu kejadian.)
tripleee

Lihat juga stackoverflow.com/a/48898886/874188 untuk bagaimana cara mengganti berbagai umum lainnya Perl lolos seperti \w, \s, dll
tripleee

102

Bagaimana kalau menggunakan grep -E?

echo "This is 02G05 a test string 20-Jul-2012" | grep -Eo '[0-9]+G[0-9]+'

3
+1 Ini lebih sederhana, dan juga akan menangani kasus beberapa kecocokan dengan benar pada baris yang sama. sedSkrip yang rumit dapat dibuat untuk kasus itu, tetapi mengapa repot-repot?
tripleee

egrepmenggunakan regexp diperpanjang, seddan grepmenggunakan regexp standar, egrepatau grep -eatau sed -Emenggunakan regexp diperpanjang, dan kode python dalam pertanyaan menggunakan PCRE, (perl ekspresi reguler umum) GNU grep dapat menggunakan PCRE dengan -Popsi.
Felipe Buccioni

@FelipeBuccioni sebenarnya yang seharusnya egrepatau grep -Eataused -r
SensorSmith

Untuk satu pertandingan (pertama), tambahkan `| head -1` (tanpa backticks), sesuai jawaban untuk pertanyaan lain ini.
SensorSmith

1
grepharus -m 1berhenti setelah pertandingan pertama.
tripleee


5

Coba ini sebagai gantinya:

echo "This is 02G05 a test string 20-Jul-2012" | sed 's/.* \([0-9]\+G[0-9]\+\) .*/\1/'

Tapi perhatikan, jika ada dua pola dalam satu baris, itu akan mencetak yang ke-2.


Atau lebih umum yang terakhir jika ada beberapa kecocokan.
tripleee

0

Coba gunakan rextract . Ini akan memungkinkan Anda mengekstrak teks menggunakan ekspresi reguler dan memformatnya ulang.

Contoh:

$ echo "This is 02G05 a test string 20-Jul-2012" | ./rextract '([\d]+G[\d]+)' '${1}'

2G05

Jika ini menggunakan regex standar, tanda kurung siku di sekelilingnya \dbenar-benar berlebihan.
tripleee
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.