Bir değişkenin bash'de birden fazla boş olmayan satır olup olmadığını nasıl test edebilirim?


10

Diyelim ki bash'da iki değişkenim var:

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

Bir değişken aslında birden fazla metin satırı içerdiğinde, sondaki yeni satır karakterlerini göz ardı ederek tespit etmek istiyorum.

Yani bu:

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

yazdırır yesve bu:

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

yazdırır no.

Özel durumum için, boş satırlara liderlik etmekten endişe etmem gerektiğini düşünmüyorum, ancak bunu nasıl yapacağımı bilmek incitmez.

Bunu nasıl yapabilirim?



@krowe Teşekkürler, ancak boş satırları yok sayan belirli bir yanıtı işaret edebilir misiniz? Ben görmedim. (Ayrıca başlığı da buna göre düzenledi.)
jpmc26

Yanıtlar:


5

Bildiğim en basit çözüm:

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

Örneğin:

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

Yukarıdakiler tüm boş çizgileri yok sayar: lider, arka ve iç. Ancak, en az iki boş olmayan çizgi olmadığı sürece bir iç boş çizgiye sahip olmanın mümkün olmadığını unutmayın, bu nedenle varlığı, önde gelen ve sondaki boş çizgileri kırptıktan sonra birden fazla çizgi olup olmadığı sorusunu değiştiremez.


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

Sed kullanarak boşlukları ve boş satırları düzeltme / silme hakkında daha fazla bilgi için /programming/16414410/delete-empty-lines-using-sed adresine bakın
.

Şimdi satır sayısını almak için tırnak içine if expression ...kullanımınızı yazmak $( ... )ve sayıya karşı test etmek için:

eğer ["$ (echo" $ MULTILINE "| sed -re '/ ^ $ / d' | wc -l)" -gt 1]; sonra
  echo 'birden fazla satır'; 
Başka 
  echo 'tek satır veya satır yok'; 
fi

0

Bu kodda küçük bir değişiklik yapılması gerekir. Bu şekilde yeniden kullanmak için kendi komut dosyasına koyabilirsiniz:

#!/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

Daha sonra bu şekilde kullanabilirsiniz (önceki komut dosyasını adlandırdığınız varsayılarak 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

İlkinde bir sözdizimi hatası alıyorum fi. Ne yazık ki, bash 3.1 (msysgit sürümü) takılı kaldım. Bana bir sözdizimi hatası gibi görünen bir şey görmüyorum, ama belli ki bir şey eksik. Düşünceler?
jpmc26

@ jpmc26 Bir hata oluştu. Harici komut dosyası olarak güncelledim, böylece kullanımı daha kolay.
krowe

@ jpmc26 Diğer tek girişi test etmek için biraz daha kontrol ekledim.
krowe

0

Sondaki boş satırları yoksayma

İşte bir yaklaşım awk:

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

Nasıl çalışır:

  • echo "$ TEST"

    Bu, ilgilendiğimiz kabuk değişkenini alır ve standart çıktıya gönderir.

  • tac

    Bu, satırların sırasını tersine çevirir, böylece son satır önce döndürülür. Yürütüldükten sonra tac, takip eden çizgiler önde gelen çizgiler haline gelir.

    (Adı tac, tersini yapan şeyi catyapan nedenin tersidir.)taccat

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

    Bu, ilk boş olmayan satırın satır numarasını değişkene kaydeder f. Tüm satırlarda okuduktan sonra f, toplam satır sayısı ile karşılaştırılır NR. eğer feşit ise NR, sadece tek bir satır vardı (ilk boşlukları yok sayarak) ve 0 koduyla çıkarız. İlk boş satırdan sonra bir veya daha fazla satır varsa, `` code ile çıkar.

  • && echo "Found A Single Line"

    awk0 kodundan çıkarsa , echoifade yürütülür.

Ön ve arka boş satırları yok sayma

Bir ek awkdeğişken oluşturarak , testi hem önde gelen hem de arkadaki boş satırları yok sayacak şekilde genişletebiliriz:

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

awkKodun bu sürümü hem öncü hem de sondaki boşlukları işlediğinden, tacartık gerekli değildir.

awkKodu her seferinde bir parça almak :

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

    Değişken firstsıfırsa (veya henüz ayarlanmadıysa) ve satırda bir karakter varsa, herhangi bir karakter varsa firstsatır numarasına ayarlanır . Ne zaman awksatırları okuyan yapılır, firstilk boş olmayan hattının hat numarasına ayarlanacaktır.

  • /./ {last=NR}

    Satırda herhangi bir karakter varsa, değişkeni lastgeçerli satır numarasına ayarlayın. Ne zaman awktüm hatları okuma yapılır, bu değişken irade son boş olmayan hattının hat numarası vardır.

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

    Bu, tüm satırlar okunduktan sonra yürütülür. Eşitse first, lastsıfır veya boş olmayan satırlar gördük ve awkkodla çıktık 0. Aksi takdirde kodla çıkar 1. Kabuk betiği çıkış kodunu her zamanki gibi ififadelerle veya &&veya ile test edebilir ||.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.