Regex yang akan menerima angka setelah string tertentu

8

Jadi saya punya garis:

ID: 54376

Bisakah Anda membantu saya membuat regex yang hanya akan mengembalikan nomor tanpa "ID:"?

CATATAN: String ini ada dalam file.

Blake Gibbs
sumber

Jawaban:

14

Coba ini:

grep -oP '(?<=ID: )[0-9]+' file

atau:

perl -nle 'print $1 if /ID:.*?(\d+)/' file
cuonglm
sumber
Terima kasih atas balasannya tetapi saya tidak memerlukan semua angka dari file, hanya perlu nomor yang muncul setelah ID:
Blake Gibbs
Memperbarui jawaban saya.
cuonglm
1
Perhatikan bahwa -odan -Padalah GNU ekstensi untuk grep. -obekerja di BSD juga. Dukungan PCRE -Ptidak selalu dikompilasi dengan baik.
Matt
4

Gunakan egrepdengan -oatau grepdengan -Eoopsi untuk mendapatkan hanya segmen yang cocok. Gunakan [0-9]sebagai regex untuk mendapatkan nomor saja:

grep -Eo [0-9]+ filename
Rohit Jain
sumber
1
OP membutuhkannya agar cocok hanya setelah string tertentu. Lihat judul pertanyaan.
terdon
4

Ada banyak cara untuk melakukan ini. Sebagai contoh:

  1. Gunakan GNU grepdengan PCRE terbaru dan cocokkan angka setelah ID::

    grep -oP 'ID:\s*\K\d+' file
    
  2. Gunakan awkdan cukup cetak bidang terakhir dari semua baris yang dimulai denganID:

    awk '/^ID:/{print $NF}' file
    

    Itu juga akan mencetak bidang yang bukan angka, untuk mendapatkan angka saja, dan hanya di bidang kedua, gunakan

    awk '($1=="ID:" && $2~/^[0-9]+$/){print $2}' file
    
  3. Gunakan GNU grep dengan Ekspresi Reguler Diperpanjang dan parsing dua kali:

    grep -Eo '^ID: *[0-9]+' file | grep -o '[0-9]*'
    
terdon
sumber
Terima kasih! Apa \Kyang dilakukan dalam contoh pertama?
rnd_d
2
@rnd_d ini adalah konstruk Ekspresi Reguler Kompatibel Perl (PCRE) yang berarti "abaikan apa pun yang cocok dengan titik ini". Ini digunakan seperti melihat di belakang, mari kita gunakan -ountuk mencetak hanya bagian yang cocok tetapi juga membuang hal-hal yang saya tidak tertarik. Bandingkan echo "foobar" | grep -oP "foobar"danecho "foobar" | grep -oP 'foo\Kbar'
terdon
4
sed -n '/ID: 54376/,${s/[^ 0-9]*//g;/./p}'

Itu hanya akan mencetak semua angka dan spasi yang terjadi setelah ID: 54376input file apa pun.

Saya baru saja memperbarui sedikit di atas untuk membuatnya sedikit lebih cepat dengan *dan tidak pmerusak garis kosong setelah menghapus karakter non-{numeric, spasi}.

Ini alamat baris dari regex /ID: 54376/ ,melalui yang $terakhir dan pada mereka s///menghapus semua atau *karakter apa pun ^tidak [^ 0-9]*kemudian pmerusak /setiap /baris dengan .karakter yang tersisa.

DEMO:

{
echo line 
printf 'ID: 54376\nno_nums_or_spaces\n'
printf '%s @nd 0th3r char@cter$ %s\n' $(seq 10)
echo 'ID: 54376'
} | sed -n '/ID 54376/,${s/[^ 0-9]*//g;/./p}'

KELUARAN:

 54376
1  03  2
3  03  4
5  03  6
7  03  8
9  03  10
 54376
mikeserv
sumber
1

Menggunakan sed:

{
    echo "ID: 1"
    echo "Line doesn't start with ID: "
    echo "ID: Non-numbers"
    echo "ID: 4"
} | sed -n '/^ID: [0-9][0-9]*$/s/ID: //p'

Ini -nadalah "jangan cetak apa pun secara default", /^ID: [0-9][0-9]*$/adalah "untuk baris yang cocok dengan regex ini" (dimulai dengan "ID:", lalu 1 digit atau lebih, lalu ujung baris), dan s/ID: //pisian formulir s/pattern/repl/flags- sartinya kita sedang melakukan pengganti, untuk mengganti pola "ID: "dengan teks pengganti ""(string kosong) menggunakan pbendera, yang berarti "cetak baris ini setelah melakukan penggantian".

Keluaran:

1
4
godlygeek
sumber
Ini tidak akan berfungsi jika ID ada di tengah-tengah baris.
Avinash Raj
Seharusnya juga tidak, berdasarkan pembacaan saya atas pertanyaan itu. Dan tidak mencoba menangani kasus secara prematur membuat kode lebih sederhana dan lebih portabel.
godlygeek
0

Perintah sed GNU lain,

sed -nr '/ID: [0-9]+/ s/.*ID: +([0-9]+).*/\1/p' file

Ini mencetak nomor apa pun setelah ID:

Avinash Raj
sumber
Anda benar-benar tidak membutuhkannya +. Jika perbedaan antara satu karakter dan 3 karakter adalah naskah Anda mungkin tidak bekerja di semua seds Anda mungkin harus melakukan: sed -n '/ID: \([0-9][0-9]*\).*/{s//\1/;s/.*[^0-9]//;/./p}'. Jawaban Anda juga meleset ID: [0-9]pada baris pertama yang berisi dua kejadian ID: [0-9].
mikeserv
0

Gunakan grep + awk:

  grep "^ID" your_file | awk {'print $2'}

Bonus: mudah dibaca :)

bunga bakung
sumber
1
Anda tidak perlu grepjika menggunakan awk. awk '/^ID/ { print $2 }'melakukan hal yang sama, dan menghindari masalah line-buffering grep . Ini juga hampir sama dengan salah satu solusi dalam jawaban @ terdon.
cas