Bagaimana cara menguji apakah suatu variabel memiliki beberapa baris non-kosong di bash?

10

Katakanlah saya memiliki dua variabel dalam bash:

MULTILINE="I have
more than one line"
SINGLE_LINE="I only have one line
"

Saya ingin mendeteksi ketika suatu variabel benar-benar berisi lebih dari satu baris teks, mengabaikan tambahan karakter baris baru.

Jadi ini:

if [ some test on "$MULTILINE" ]; then echo 'yes'; else echo 'no'; fi

akan dicetak yes, dan ini:

if [ some test on "$SINGLE_LINE" ]; then echo 'yes'; else echo 'no'; fi

akan dicetak no.

Untuk kasus spesifik saya, saya pikir saya tidak perlu khawatir tentang memimpin garis kosong, tetapi tidak ada salahnya untuk mengetahui cara melakukannya.

Bagaimana saya bisa melakukan ini?

jpmc26
sumber
@krowe Terima kasih, tetapi dapatkah Anda menunjuk ke jawaban spesifik di sana yang mengabaikan garis kosong yang tertinggal? Saya tidak melihat apa pun. (Juga diedit judulnya.)
jpmc26

Jawaban:

5

Solusi paling sederhana yang saya tahu adalah:

if (( $(grep -c . <<<"$MULTILINE") > 1 ))

misalnya:

VAR="a
b"
if (( $(grep -c . <<<"$VAR") > 1 )); then
  echo VAR has more than one line
else
  echo VAR has at most one line
fi

==>

VAR has more than one line

Di atas mengabaikan semua garis kosong: depan, belakang dan interior. Tetapi perhatikan bahwa tidak mungkin memiliki garis dalam interior kecuali jika ada setidaknya dua garis tidak kosong, sehingga keberadaannya tidak dapat mengubah pertanyaan apakah ada lebih dari satu garis setelah pemangkasan garis kosong awal dan belakang.

rici
sumber
5
$ echo "$ MULTILINE" | wc -l
2

$ echo "$ SINGLE_LINE" | wc -l
2

$ echo "$ SINGLE_LINE" | sed -re '/ ^ $ / d' | wc -l
1

$ echo "$ MULTILINE" | sed -re '/ ^ $ / d' | wc -l
2

Lihat /programming/16414410/delete-empty-lines-using-sed
untuk informasi lebih lanjut tentang cara memotong / menghapus spasi dan menghapus baris menggunakan sed.

Sekarang, tulis if expression ...penggunaan Anda $( ... )di dalam kutipan untuk mendapatkan jumlah baris, dan uji terhadap nomor:

if ["$ (echo" $ MULTILINE "| sed -re '/ ^ $ / d' | wc -l)" -gt 1]; kemudian
  gema 'lebih dari satu baris'; 
lain 
  gema 'single or no line'; 
fi
Hannu
sumber
0

Sedikit modifikasi pada kode ini harus dilakukan. Anda dapat memasukkannya ke dalam skrip sendiri untuk digunakan kembali seperti ini:

#!/bin/bash
nlhit=""
for (( i=0; i<${#1}; i++ )); do
    if [[ "${1:$i:1}" == $'\n' ]]; then
        nlhit="1"
    elif [[ "$nlhit" == "1" ]]; then
        exit 1
    fi
done

exit 0

Kemudian Anda dapat menggunakannya seperti itu (dengan asumsi bahwa Anda menamai skrip sebelumnya multiline-check.sh):

#!/bin/bash

EMPTYLINE=""
BLANKLINE="    "
ONLYLINES="


"

MULTILINE="I have
more than one line"
SINGLE_LINE="I only have one line
"
SECOND_LINE="
I begin with a newline"


echo -n "EMPTYLINE Check: "
multiline-check.sh "$EMPTYLINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "BLANKLINE Check: "
multiline-check.sh "$BLANKLINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "ONLYLINES Check: "
multiline-check.sh "$ONLYLINES"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "MULTILINE Check: "
multiline-check.sh "$MULTILINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "SINGLE_LINE Check: "
multiline-check.sh "$SINGLE_LINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "SECOND_LINE Check: "
multiline-check.sh "$SECOND_LINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi
Krowe
sumber
Saya mendapatkan kesalahan sintaks pada yang pertama fi. Sayangnya, saya terjebak di bash 3.1 (versi msysgit). Saya tidak melihat apa pun yang tampak seperti kesalahan sintaksis bagi saya, tetapi jelas saya kehilangan sesuatu. Pikiran?
jpmc26
@ jpmc26 Memang ada kesalahan. Saya telah memperbarui ini menjadi skrip eksternal sehingga lebih mudah digunakan juga.
krowe
@ jpmc26 Saya telah menambahkan beberapa pemeriksaan lagi untuk menguji input ganjil lainnya.
krowe
0

Mengabaikan garis kosong yang tertinggal

Berikut ini adalah pendekatan menggunakan awk:

echo "$TEST" | tac | awk 'f==0 && /./ {f=NR} END{if(f==NR){exit 0}; exit 1 }' && echo "Found A Single Line"

Bagaimana itu bekerja:

  • gema "$ TEST"

    Ini mengambil variabel shell apa pun yang kami tertarik dan mengirimkannya ke standar keluar.

  • tac

    Ini membalik urutan garis sehingga baris terakhir dikembalikan terlebih dahulu. Setelah dieksekusi tac, garis trailing menjadi garis terdepan.

    (Nama tacadalah kebalikan dari catuntuk alasan yang tacmelakukan apa cattetapi sebaliknya.)

  • awk 'f==0 && /./ {f=NR} END{if(f==NR){exit 0}; exit 1 }'

    Ini menyimpan nomor baris dari baris non-kosong pertama dalam variabel f. Setelah membaca semua baris, ia membandingkan fdengan jumlah total baris NR,. jika fsama dengan NR, maka kita hanya memiliki satu baris (mengabaikan kosong awal) dan kita keluar dengan kode 0. Jika ada satu atau lebih baris setelah baris kosong pertama, maka ia keluar dengan kode `.

  • && echo "Found A Single Line"

    Jika awkkeluar dengan kode 0, maka echopernyataan dieksekusi.

Mengabaikan garis depan dan belakang yang kosong

Dengan membuat satu awkvariabel tambahan , kita dapat memperluas tes untuk mengabaikan garis depan dan belakang yang kosong:

echo "$TEST" | awk 'first==0 && /./ {first=NR} /./ {last=NR} END{if(first==last){exit 0}; exit 1 }' && echo " Found A Single Line"

Karena versi awkkode ini menangani bagian awal dan akhir kosong, tactidak lagi diperlukan.

Mengambil awkkode satu per satu:

  • first==0 && /./ {first=NR}

    Jika variabelnya firstnol (atau belum disetel) dan garis memiliki karakter, karakter apa pun, lalu setel firstke nomor baris. Setelah awkselesai membaca baris, firstakan diatur ke nomor baris dari baris pertama yang tidak kosong.

  • /./ {last=NR}

    Jika baris memiliki karakter di dalamnya, maka atur variabel lastke nomor baris saat ini. Ketika awkselesai membaca semua baris, variabel ini akan memiliki nomor baris dari baris non-kosong terakhir.

  • END{if(first==last){exit 0}; exit 1 }

    Ini dieksekusi setelah semua baris telah dibaca. Jikafirst sama dengan last, maka kita telah melihat nol atau baris yang tidak kosong dan awkkeluar dengan kode 0. Kalau tidak, ia keluar dengan kode 1. Script shell dapat menguji kode keluar seperti biasa dengan ifpernyataan atau &&atau ||.

John1024
sumber