Ekstrak bagian dari satu baris dari file dengan sed

18

Saya ingin membaca satu bagian dari satu baris dari sebuah file. Sebagai contoh:

POP3_SERVER_NAME = localhost

Saya ingin kembali saja localhost, menggunakan sed.

Teks ini ada di baris ketiga. Saya melakukan ini untuk mengekstrak baris:

sed -n '3p' installation.sh

Bagaimana cara mengekstrak hanya localhostbagian?

Mercer
sumber

Jawaban:

26

awk mungkin alat yang lebih baik di sini.

$ cat test.dat
LINE 1
LINE 2
POP3_SERVER_NAME = localhost

Telusuri baris yang berisi "POP3_SERVER_NAME"; cetak kolom terakhir. Ini tidak tergantung pada POP3_SERVER_NAME yang selalu menggunakan jalur 3, yang mungkin merupakan Hal yang Baik.

$ awk '/POP3_SERVER_NAME/{print $NF}' test.dat
localhost

Bergantung pada aplikasi Anda, Anda mungkin perlu membuat ekspresi reguler lebih ketat. Misalnya, Anda mungkin ingin mencocokkan hanya garis yang dimulai dengan POP3_SERVER_NAME.

$ awk '/^POP3_SERVER_NAME/{print $NF}' test.dat
localhost

Menggunakan sed sedikit kurang intuitif. (Terima kasih, saya menyadari ironi ini.) Alamat baris yang berisi POP3_SERVER_NAME di mana saja. Ganti string kosong untuk semua teks dari awal baris ke spasi opsional setelah "=". Lalu cetak.

sed -n -e '/POP3_SERVER_NAME/ s/.*\= *//p' test.dat
Mike Sherrill 'Cat Recall'
sumber
2
The awkperintah bagus - tetapi hanya jika Anda punya ruang di sekitar =. Itu tidak akan berhasil POP3_SERVER_NAME=localhost.
Marcel Stör
2
@ Marscel, Anda dapat mengubah pembatas yang digunakan oleh awkdari spasi ke yang lain menggunakan -F. Misalnya: -F "="akan menggunakan =sebagai pembatas dalam kasus yang Anda sebutkan.
mattpr
7

Ganti pperintah dengan substitusi yang menghilangkan bagian yang tidak diinginkan dari baris.

sed -n '3 s/^[^=]*= *//p' installation.sh

Anda mungkin ingin mencocokkan baris dengan kata kunci daripada dengan posisi.

sed -n 's/^ *POP3_SERVER_NAME *= *//p' installation.sh
Gilles 'SANGAT berhenti menjadi jahat'
sumber
6

Sepertinya Anda punya file konfigurasi. Apa yang dapat Anda lakukan mirip dengan apa yang disarankan Adam Siemeon / slm:

sed -nr 's/[^=]+=\s*(.+)$/\1/p' filename

di mana [^=]tidak termasuk semua '=' karakter, +kata salah satu atau lebih dari jenis yang sama dari karakter, ini diikuti oleh yang sebenarnya =, \ssetiap spasi (termasuk tab \tdan baris baru \n, \r\n, dan ruang polos '', sedangkan *berarti nol atau lebih dari jenis yang sama , tanda kurung menangkap apa yang ada di dalam untuk menempatkan urutan karakter yang cocok ke dalam penampung pengganti \ 1, \ 2, ..., \ n, $berarti akhir dari sebuah baris. Ini mengikuti pola penggantian khas:. s/.../.../modifiersOpsi baris perintah -radalah singkatan dari sintaks regex diperpanjang (sebagai masalah kenyamanan) dan -nberarti tidak menghasilkan apa-apa sampai atau kecuali diminta secara eksplisit. pPengubah mencetak hasil.

Anda dapat melakukan pencarian global dengan gpengubah seperti:

sed -nr 's/[^=]+=\s*(.+)$/\1 /pg' filename  # note the space after \1

sehingga Anda mendapatkan string dipisahkan oleh ' '(bisa \n, \tatau apa yang harus Anda) yang dapat Anda memproses dengan mudah.

Keduanya valid asalkan nilai Anda didahului oleh rentang karakter persamaan hingga akhir baris dan tidak diikuti oleh komentar atau karakter lain dengan semantik yang menyimpang dari "nilai" sederhana.


Edit:

Saya belum bisa berkomentar di sini tentang posting orang lain. Untuk menunjukkan baris, cukup lewati nomor baris, dalam kasus Anda 3, sebelum satau sebelum tanda kutip yang dimulai (seperti dalam vim).

sed -nr '3s/[^=]+=\s*(.+)$/\1/p' filename

Silakan lihat info sed. Misalnya, 3.2 dan 4.7 menarik bagi Anda.

Nicholas
sumber
5
echo "POP3_SERVER_NAME = localhost" | sed 's/.*= //'
localhost

Atau jika Anda memiliki konten dalam file:

sed 's/.*= //' somefile.txt
localhost
Adam Siemion
sumber
ok, tapi saya baca di file saya seperti ini: sed -n '3p' installation.sh
Mercer
2
@Mercer - lihat pembaruan yang saya tambahkan ke jawabannya.
slm
@Adam Siemion - terima kasih, tetapi bagaimana cara menunjukkan nomor baris?
Mercer
4

Anda dapat menggunakan perintah potong, mengatur delimeter ke '=' dan kemudian mencetak bidang kedua seperti ini:

cut -d'=' -f2
anselal
sumber
3

Berbagai cara untuk melakukannya, mengingat file Anda disebut foobar:

Tentukan pola yang akan dicari:

PAT=POP3_SERVER_NAME

Ekstrak menggunakan sed

sed -n "/$PAT/p" foobar | sed "s/$PAT = //"

Atau menggunakan seddancut

sed -n "/$PAT/p" foobar | cut -d' ' -f3
unxnut
sumber
2

Keindahan Linux / Unix adalah bahwa biasanya ada lebih dari satu cara untuk mencapai sesuatu. Dalam kasus op, setidaknya ada empat cara berbeda untuk mengekstrak nama server POP dari file:

  1. grep POP3_SERVER_NAME installation.sh | cut -d'=' -f2
  2. grep POP3_SERVER_NAME installation.sh | awk '{print $3}'
  3. grep POP3_SERVER_NAME installation.sh | sed 's/.*= //'
  4. sed -n 's/^.*POP3_SERVER_NAME = //p' installation.sh
Terima kasih
sumber