コロン文字がBashで私のパターンマッチングを混乱させる

コロン文字がBashで私のパターンマッチングを混乱させる

$line次の文字列のいずれかを含めることができる変数があります。

  • line="READ CACHE IS: ENABLED"
  • line="BLOCKS READ CACHE AND SENT TO INITIATOR = 2489338280"
  • line="ECC REREADS/ ERRORS ALGORITHM PROCESSED UNCORRECTED"
  • line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"
  • line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"
  • line="0x22 GPL R/O 1 READ STREAM ERROR LOG"
  • line="READ: DISABLED"

$line変数をいくつかのパターンと比較するスクリプトがあります。

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] || 
[[ ${line} == "READ\:"* ]] && 
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')

それが問題だ。コロンはすべてを台無しにします。上記のように:をエスケープするときに、両方の可能性をline="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"満たすようにパターンをフォーマットするすべての可能な方法を試しました。line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"満足できline="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"ましたがline="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"…脱出を奪うとline="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"満足できないline="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"

実行例1:

line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"

        if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] || 
           [[ ${line} == "READ\:"* ]] && 
           [[ ${line} != *"READ: DISABLED"* ]]; then

          devReadErr=$(echo "$line" | awk '{print $8}')
        fi

echo $devReadErr

実行1の出力:

0

実行例2:

line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

        if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] || 
           [[ ${line} == "READ\:"* ]] && 
           [[ ${line} != *"READ: DISABLED"* ]]; then

          devReadErr=$(echo "$line" | awk '{print $8}')
        fi

echo $devReadErr

実行2の出力:

<null>

実行例3:

line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

        if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] || 
           [[ ${line} == "READ:"* ]] && 
           [[ ${line} != *"READ: DISABLED"* ]]; then

          devReadErr=$(echo "$line" | awk '{print $8}')
        fi

echo $devReadErr

実行3の出力:

0

どうすれば両方の世界の利点を得ることができますか?

答え1

2番目のテストでは、\前の項目を削除する必要があります。それ以外の場合は、リテラル文字:と一致しようとします。\

これは、実行中の正規表現の一致ではなく、シェルワイルドカードパターンの一致です(*コマンドラインでパターンに使用する場合と同じです)。この場合は問題ではありません。

最初の2つの文字列から20を抽出して保存しようとしていますdevReadErrが、行を読み取るときはそうでないとしますREAD: DISABLED。削除された場合、\コードが実行する操作は次のとおりです。

if  [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
    [[ ${line} == "READ:"* ]] &&
    [[ ${line} != *"READ: DISABLED"* ]]; then

    devReadErr=$(echo "$line" | awk '{print $2}')

fi

同じタスクを実行する別の方法:

if [[ "$line" != *'DISABLED' ]]; then
    devReadErr=${line##* }
fi

$line文字列が単語で終わらない場合、数字は最後の空白文字の後の文字列として抽出されますDISABLED。これはとechoを防ぎますawk

awkこれがファイルを1行ずつ解析するより大きなループの一部である場合は、テキストを解析するように設計された別の言語で書くことをお勧めします。たとえば、次を参照してください。 シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?

答え2

私はあなたが欲しいと思います:

if [[ $line = *RAW_READ_ERROR_RATE* || 
      $line = READ:* && $line != *"READ: DISABLED"* ]]; then

演算子が&& [[...]]優先され||ますが&& シェル演算子はと同じ優先順位を持ちます||

または明示的に:

if [[ $line = *RAW_READ_ERROR_RATE* || 
      ($line = READ:* && $line != *"READ: DISABLED"*) ]]; then

または、複数のsで&&/シェル演算子を使用してください。||[[...]]

if [[ $line = *RAW_READ_ERROR_RATE* ]] || { 
      [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]]; }; then

または順序を変更してください。

if [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]] ||
   [[ $line = *RAW_READ_ERROR_RATE* ]]; then

または、すべてに一致するパターンを使用します。

if [[ $line = @(*RAW_READ_ERROR_RATE*|!(!(*READ:*)|*READ:\ DISABLED*)) ]]; then

括弧/中括弧がない場合、コンテンツは次のように解釈されます。

if [[ ($line = *RAW_READ_ERROR_RATE* || 
     $line = READ:*) && $line != *"READ: DISABLED"* ]]; then

これは、whileRAW_READ_ERROR_RATEが含まれていない場合に含まれる行と一致することを妨げてはいけませんREAD: DISABLED

関連情報