Dapat grep mengembalikan true / false atau ada metode alternatif

130

Sebagai bagian dari skrip ini, saya harus dapat memeriksa apakah argumen pertama yang diberikan cocok dengan kata pertama dari file. Jika ya, keluar dengan pesan kesalahan; jika tidak, tambahkan argumen ke file. Saya mengerti bagaimana menulis ifpernyataan, tetapi tidak bagaimana menggunakannya grepdalam skrip. Saya mengerti bahwa grepakan terlihat seperti ini

grep ^$1 schemas.txt

Saya merasa ini seharusnya lebih mudah daripada saya membuatnya.

Saya mendapat kesalahan "terlalu banyak argumen" pada ifpernyataan itu. Saya menyingkirkan ruang antara grep -qdan kemudian mendapat kesalahan yang diharapkan operator biner.

if [ grep -q ^$1 schemas.txt ]
then
        echo "Schema already exists. Please try again"
        exit 1
else
        echo "$@" >> schemas.txt
fi
Lauren
sumber
1
Kalah [... ]dan itu akan berhasil. Meskipun Anda mungkin ingin mengutip pola Anda:if grep -q "^$1" schemas.txt; then …
derobert
satu solusi garis menggunakan fitur "Perintah Grup" Bash: stackoverflow.com/questions/6550484/…
Trevor Boyd Smith

Jawaban:

186

grepmengembalikan kode keluar yang berbeda jika ia menemukan sesuatu (nol) vs. jika belum menemukan apa pun (bukan nol). Dalam sebuah ifpernyataan, kode keluar nol dipetakan ke "true" dan kode keluar bukan nol dipetakan ke false. Selain itu, grep memiliki -qargumen untuk tidak menampilkan teks yang cocok (tetapi hanya mengembalikan kode status keluar)

Jadi, Anda bisa menggunakan grep seperti ini:

if grep -q PATTERN file.txt; then
    echo found
else
    echo not found
fi

Sebagai catatan singkat, ketika Anda melakukan sesuatu seperti if [ -z "$var" ]…, ternyata itu [sebenarnya adalah perintah yang Anda jalankan, seperti halnya grep. Di sistem saya, itu /usr/bin/[. (Yah, secara teknis, shell Anda mungkin sudah built-in, tapi itu optimasi. Berperilaku seolah-olah itu adalah perintah). Ini bekerja dengan cara yang sama, [mengembalikan kode keluar nol untuk true, kode keluar non-nol untuk false. ( testsama dengan [, kecuali untuk penutupan ])

derobert
sumber
Mengapa pernyataan if tidak membutuhkan tanda kurung? Saya memilikinya bekerja tanpa, tetapi tidak mengerti mengapa. Bisakah saya tetap bersarang tanpa tanda kurung?
Lauren
@Lauren apakah Anda melewatkan pesan singkat? [bukan bagian dari sintaks if, ini (secara konseptual) adalah perintah yang Anda jalankan, seperti halnya grep
derobert
2
@Lauren Anda tidak menggunakan grep dalam [, Anda menggunakan satu atau yang lain, tergantung pada kondisi apa yang ingin Anda periksa. (Anda dapat menggunakan perintah apa pun di dalam if, btw, jika hanya memeriksa kode keluar.) ... well, saya kira Anda mungkin dapat menemukan alasan untuk menggunakan grep di dalam [, tetapi itu akan menjadi skrip yang cukup rumit, dan itu bukan hal yang normal untuk dilakukan.
derobert
3
FYI, jalankan ls -l /usr/bin/\[dan man [lihat itu [adalah program seperti yang lain, itu hanya terlihat seperti elemen sintaksis - ini harus membuatnya jelas dan lebih mudah dimengerti. (untuk kenyamanan, [ini juga merupakan built-in di bash, dash, dan lain-lain - tetapi masih perintah). coba juga type -all [di bash.
cas
1
@AlexanderCska jika Anda ingin grep untuk mencetak garis yang cocok (mis., Untuk memasang pipa di suatu tempat), kemudian abaikan -q, opsi itu memberi tahu grep untuk diam (tidak mencetak garis yang cocok).
derobert
48

Cara sederhana lainnya adalah menggunakan grep -c.

Output itu (tidak kembali sebagai kode keluar), jumlah baris yang cocok dengan pola, jadi 0 jika tidak ada kecocokan atau 1 atau lebih jika ada kecocokan.

Jadi, jika Anda ingin memeriksa bahwa polanya cocok 3 kali atau lebih, Anda akan melakukannya:

if [ "$(grep -c "^$1" schemas.txt)" -ge 3 ]; then
  ...
amigal
sumber
17
Lebih tepatnya, itu akan menghasilkan 1 jika ditemukan hanya sekali. Untuk menghasilkan 1 terlepas dari jumlah pertandingan yang ditemukan gunakan grep -cim1sebagai gantinya.
manatwork
Metode ini juga dapat digunakan untuk membedakan antara grep error dan grep 'pattern found 0 times'. (Meskipun tidak dengan pernyataan jika tepat digunakan, saya pikir variabel diperlukan)
Evan Benn
3

Saya tahu saya terlambat untuk ini, tapi saya suka versi pendek ini:

grep -q ^$1 schemas.txt && echo "Schema already exists. Please try again" || echo "$@" >> schemas.txt
Denis Pitzalis
sumber
0

Jika kita ingin menangkap kata pertama dari suatu file, kita perlu menambahkan -zwgrep

if grep -qzw "^$1" file
then 
   ... 
else 
   ... 
fi

Tanpa -zkita mendapatkan kata pertama dari sebuah baris. Tanpa -wkita mendapat kata-kata parsial.

Joao
sumber
-2

Jika Anda ingin menggunakannya dengan tanda kurung siku, Anda dapat mengeksekusi di bawah ini

if [ `grep -q PATTERN file.txt` ]; then
    echo found
else
    echo not found

Logika ini berfungsi untuk semua perintah, Cukup tempatkan perintah Anda di dalam backtick (tombol di atas tab atau di bawah tombol Esc atau di sebelah kiri tombol 1)

k_vishwanath
sumber
1
Anda perlu mengutip `grep -q PATTERN file.txt`, jika tidak operator split + glob diterapkan dan itu akan menyebabkan masalah untuk output apa pun yang berisi karakter $IFSatau karakter wildcard. Lebih umum, [ "`cmd`" ]akan mengembalikan true jika cmdoutput setidaknya satu baris non-kosong di stdout (dengan potensi masalah jika output NUL byte). Itu berarti shell harus menyimpan seluruh output dalam memori dan menunggu sampai selesai. if cmd | grep -q .Sebaliknya menggunakan mungkin lebih disukai dalam hal itu.
Stéphane Chazelas
Perintah ini tidak masuk akal sama sekali. Tujuan dari -qsaklar adalah untuk menekan grep output. Anda mengatakan: Periksa POLA di file.txt, tekan output apa pun, lalu atur status pengembalian sesuai dengan apakah POLA ditemukan. Kemudian, abaikan status pengembalian, ambil output perintah (yang kami terpaksa kosong), terapkan pemisahan kata dan ajukan ekspansi glob (tidak menghasilkan argumen sama sekali), lalu jalankan perintah [(alias test) dengan tepat satu argumen - yaitu , ]--dan kemudian, karena itu akan menghasilkan kesalahan, gema "tidak ditemukan". @ StéphaneChazelas, apakah saya melewatkan sesuatu?
Wildcard
1
@ Kartu Memori, Anda benar, saya tampaknya mengabaikan -q. Komentar itu masuk akal [ `grep PATTERN file.txt ` ], tetapi seperti yang ditunjukkan dalam komentar, [ "`grep -n PATTERN file.txt`" ]akan lebih baik jika POLA hanya cocok dengan baris kosong. Meskipun di sini tentu saja itu yang if grep -q PATTERN file.txtAnda inginkan.
Stéphane Chazelas