変数のbashに複数の非空白行があるかどうかをテストするにはどうすればよいですか?


10

bashに2つの変数があるとします。

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

変数の末尾の改行文字を無視して、変数に実際に複数行のテキストが含まれていることを検出したい。

したがって、この:

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

印刷しyes、これ:

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

印刷しますno

私の特定のケースでは、空白行の先頭を気にする必要はないと思いますが、その方法を知っていても問題はありません。

これどうやってするの?



@kroweありがとうございますが、末尾の空白行を無視する特定の回答をそこに示すことができますか?何も見えなかった。(それに応じてタイトルも編集しました。)
jpmc26 2014

回答:


5

私が知っている最も簡単な解決策は:

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

例えば:

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

上記はすべての空白行を無視します:先頭、末尾、内部。ただし、非空白行が2行以上ない限り、内部の空白行を作成することはできないため、その存在によって、先頭と末尾の空白行をトリミングした後、複数の行があるかどうかの問題が変わることはありません。


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

$エコー "$ SINGLE_LINE" | wc -l
2

$エコー "$ SINGLE_LINE" | sed -re '/ ^ $ / d' | wc -l
1

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

sedを使用して空白や空の行をトリミング/削除する方法の詳細については、https://stackoverflow.com/questions/16414410/delete-empty-lines-using-sed
を参照してください

今すぐあなたの書くためにif expression ...使用する $( ... )数に対して行数、およびテストを取得するには、引用符の内側:

if ["$(echo" $ MULTILINE "| sed -re '/ ^ $ / d' | wc -l)" -gt 1]; その後
  エコー '複数行'; 
そうしないと 
  エコー '単一または線なし'; 
fi

0

このコードを少し変更するだけでそれが可能になります。独自のスクリプトに入れて、次のように再利用できます。

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

その後、次のように使用できます(前のスクリプトに名前を付けた場合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

最初に構文エラーが発生しますfi。残念ながら、私はbash 3.1(msysgitバージョン)で立ち往生しています。構文エラーのように見えるものは何もありませんが、何か不足しています。考え?
jpmc26 2014

@ jpmc26エラーがありました。使いやすくするために、スクリプトを外部スクリプトに更​​新しました。
krowe 2014

@ jpmc26他の奇妙な入力をテストするために、いくつかのチェックを追加しました。
krowe 2014

0

末尾の空白行を無視する

以下は使用するアプローチawkです:

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

使い方:

  • 「$ TEST」をエコー

    これは、興味のあるシェル変数を受け取り、標準出力に送信します。

  • tac

    これにより、行の順序が逆になり、最後の行が最初に返されます。を実行するtacと、後続行が先頭行になります。

    (名前tacは何をするかcatという理由で逆になっていますが、逆です。)taccat

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

    これにより、最初の空白以外の行の行番号が変数に格納されますf。すべての行を読み込んだ後f、合計行数と比較されNRます。fがに等しい場合NR、最初の空白行を無視して1行だけでコード0で終了します。最初の空白行の後に1行以上ある場合、コード `で終了します。

  • && echo "Found A Single Line"

    awkコード0で終了した場合、echoステートメントが実行されます。

先頭と末尾の両方の空白行を無視する

追加のawk変数を1つ作成することにより、先頭と末尾の両方の空白行を無視するようにテストを拡張できます。

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

このバージョンのawkコードは先行ブランクと後続ブランクの両方を処理するため、tac不要になりました。

撮影awk時に一部のコードを:

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

    変数firstがゼロ(またはまだ設定されていない)で、行に文字、任意の文字がある場合first、行番号に設定されます。場合awk行を読み出し実行され、first最初の非空白行の行番号に設定されます。

  • /./ {last=NR}

    行に文字が含まれている場合は、変数lastを現在の行番号に設定します。awkすべての行の読み取りが完了すると、この変数には最後の空白でない行の行番号が含まれます。

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

    これは、すべての行が読み取られた後に実行されます。firstがに等しい場合last、ゼロまたは空白以外の行awkが表示され、コードで終了します0。それ以外の場合は、コードで終了します1。シェルスクリプトは、ifステートメントまたは&&or を使用して、通常どおり終了コードをテストでき||ます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.