Bagaimana cara mencocokkan string yang tepat menggunakan `sed`? Tetapi bukan bagian dari itu.?

8

Saya memiliki file input FILE1.TXT seperti di bawah ini.


11 id1  
12  
13 AGE = 20  
14 NAME = NAME1  
15  
16 id2  
17  
18 AGE = 30  
19 NAME = NAME2  
.  
.  
.  
110 idXYZ  
111  
112 AGE = AGEXYZ  
113 NAME = NAMEXYZ  
114  
115 idZZZ  
116

Saya ingin mencari semua bidang yang memiliki ID tertentu dan mendapatkan nilai untuk NAME

Saya berhasil mengulang setiap Id dan membentuk perintah di bawah ini untuk setiap Id sebagaimana diperlukan.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'

Masalahnya di sini adalah, saya mendapatkan output NAME1 , selain itu, saya juga mendapatkan NAMEXYZ .

Apa yang harus diubah sehingga saya hanya mendapatkan NAME1 tetapi tidak NAMEXYZ ?

Sebagai solusinya, perintah di bawah ini berfungsi.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'|head -1

Apakah ada 'saklar' atau saya kehilangan sesuatu?

Vinay
sumber

Jawaban:

3

Jika Anda tahu nomor baris yang ingin Anda cari (seperti yang disarankan Q Anda), kencangkan regex sehingga Anda tidak cocok dengan baris yang tidak diinginkan.

Misalnya, ubah:

sed -n '/11/,/14/p' | grep NAME | awk -F "= " '{print $2}'

untuk

sed -n '/^11 /,/^14 /p' | grep NAME | awk -F "= " '{print $2}'

The ^akan cocok dengan awal baris dan spasi setelah jaminan nomor yang nomor baris tertentu akan cocok, dan Anda tidak akan memproses blok yang tidak diinginkan.

casey
sumber
Itu akan membantu. Tapi, Bagaimana saya bisa mencocokkan ^(random no of spaces)11?
Vinay
1
@VinayChalluru usesed -n '/^\s*11 /,/^\s*14 /p'
casey
1
bisa menggunakan tangan pendek sed -n '/^11 /,/^14 /p' | awk '/NAME/{print $NF}' apakah Anda sudah mencoba ini?
Rahul Patil
@RahulPatil Ya, Berhasil.
Vinay
6

Gunakan batas kata:

grep '\bNAME1\b'

akan cocok NAME1dan tidak NAME1XYZatau XYZNAME1.

Demikian pula,

sed -n '/11\b/,/14\b/p'

tidak akan cocok dengan baris yang berisi 111dan 142.


EDIT: Tampaknya angka-angka dalam file input sebenarnya nomor baris. Jika itu masalahnya, Anda bisa mengatakan:

sed '11,14!d'

untuk mendapatkan garis yang diinginkan.

devnull
sumber
Hanya ada satu di NAMEantara baris 11 dan 14. Jadi, mengapa sedmelihat 111dan 114? Bagaimana membuatnya tidak terlihat di antara 111dan 114?
Vinay
@VinayChalluru Lihat jawaban di atas untuk bagaimana Anda dapat memodifikasi sedekspresi.
devnull
Saya kira ini menjawab pertanyaan saya. Biarkan saya mencoba dan memberi tahu Anda.
Vinay
untuk batas kata, grepdengan -wbendera? bukan?
Rahul Patil
1
@RahulPatil Yup, untuk contoh di atas -wakan setara. Sebagai sedcontoh, -wsedikit berbeda.
devnull
4

Anda bisa menggunakan AWK

awk 'NR>=13 && NR<=17 && /NAME/{print $NF}' infile

Ini akan mencari garis antara 13 hingga 17 kemudian mencari Nama dan jika cocok maka akan mencetak kata terakhir dari Name = LastWord

Rahul Patil
sumber
Ketika saya mencoba melakukan ini, saya mendapatkan pesan kesalahan yang mengatakan bahwa nomor saluran input harus kurang dari 199.
Vinay
@VinayChalluru dapatkah Anda menunjukkan kepada saya keluaran dengan perintah, gunakan paste.ubuntu.com
Rahul Patil
Permintaan maaf. Saya menambahkan $sebelum NRdan itu menyebabkan kesalahan.
Vinay
@VinayChalluru Tidak apa-apa. itu bagus Anda mencoba / menguji masing-masing ans dan belajar sesuatu yang baru ..: D
Rahul Patil
Persis. Ada banyak lagi di depan. :-)
Vinay
4

Anda tidak memerlukan alat lain untuk ini, sedakan dengan mudah menanganinya secara keseluruhan.

sed -nr '/11/,/14/{s/^.*NAME =\s*(\S*).*$/\1/p}' <$infile

Itu seharusnya memberi Anda hanya urutan pertama karakter non-spasi putih mengikuti frasa "NAME =" untuk setiap baris tempat frasa itu ditemukan di antara baris 11 dan 14 dari setiap file input sedyang diumpankan.

mikeserv
sumber
3

sed bukan alat yang tepat untuk pekerjaan ini. Gunakan awk di mana Anda dapat menentukan id yang Anda cari dan mencetak NAME berikutnya yang muncul.

awk -v id="id2" '
    $NF == id {have_id = 1} 
    have_id && $0 ~ /NAME/ {print $NF; exit}
' filename
glenn jackman
sumber
Bisakah Anda menjelaskan baris dua dan tiga dari perintah awk Anda?
erik
0

versi generik tidak didasarkan pada nomor baris tetapi referensi id

sed -n '1h;1!H;
$ {
  x
  s/.*/&\^J/
: clean
#  put your ID pattern here in place of id9
  s/.*\(id9 *\n.*\)id[0-9]\{1,\} *\n.*/\1/
  t clean
  s/.*NAME = \([^[:cntrl:]]*\)\n.*/\1/
  p
  }' YourFile
  1. muat seluruh file
  2. bagian bersih bukan bagian dari grup id (rekursif)
  3. ambil saja nilai konten NAME dalam grup
  4. cetak hasilnya
NeronLeVelu
sumber
0

Anda dapat mencetak garis-garis yang berisi pola yang cocok menggunakan sed sebagai berikut:

sed -n '/pattern/p'  Filename
  • -n- opsi ini menonaktifkan pencetakan otomatis ini, dan sed hanya menghasilkan output ketika secara eksplisit disuruh melalui pperintah.

  • p - cetak

pengguna182845
sumber