grepにスペースを含む複数のインクルードを渡します。

grepにスペースを含む複数のインクルードを渡します。

前者Get-ChildItemSelect-String後者の使用を標準化するためにPowerShellとBashスクリプトを作成していますgrep

Bashスクリプトの一部としてコマンドライン引数を使用して(を含むカンマ区切りのファイル名の値を解析します)。複数形)これをGrepに伝えようとしましたが、--include=いくつかの困難に遭遇しました。

最初は中かっこ拡張を試してみましたが、(1)正しく動作しなかったこと、(2)grepは技術的にこれをサポートしていません。とにかく複数が含まれています。

これで、正常に処理された複数のインクルードを使用しようとしていますが、値にスペースが含まれていない場合にのみその値が引用符で囲まれていないため、スクリプトは何もしません$grepstring。シェルのコピーと貼り付けの出力は正しく機能しますが、引用されたバージョンを機能させることはできません。

以下はスクリプトの単純化されたバージョンです。

#!/bin/bash

include="$1"

if [[ $include == *","* ]]; then
    IFS=',' read -r -a includearray <<< "$include"
    
    includemulti=""
    
    firstloop="yes"
    
    for element in "${includearray[@]}"
    do
        # Trim leading and trailing whitespace
        element="${element## }"
        element="${element%% }"
        
        if [[ "$firstloop" == "yes" ]]; then
            firstloop="no"
            includemulti+="--include=$element"
            # includemulti+="--include=\"$element\""
            # includemulti+="--include='"$element"'"
            # includemulti+='--include="'$element'"'
            # includemulti+='--include="'"$element"'"'
            # includemulti+="--include='$element'"
        else
            includemulti+=" --include=$element"
            # includemulti+=" --include=\"$element\""
            # includemulti+=" --include='"$element"'"
            # includemulti+=' --include="'$element'"'
            # includemulti+=' --include="'"$element"'"'
            # includemulti+=" --include='$element'"
        fi
    done
    
    grep -ERins $includemulti "<pattern>" "<path>"
    
    grepstring="grep -ERins $includemulti \"<pattern>\" \"<path>\""
    echo $grepstring
else
    grep -ERins --include="$include" "<pattern>" "<path>"
fi

効率的な:

bash ~/test.sh 'Hello*.txt, *.sh'

bash ~/test.sh 'Hello W*.txt'

動作しません:

bash ~/test.sh 'Hello W*.txt, *.sh'

何度も呼び出す方が簡単かどうか疑問になり始めました。grep各呼び出しには以下が含まれます。

ベストアンサー1

分析する

入力が次の場合、'Hello W*.txt, *.sh'スペースは区切り文字として使用されます。だからあなたはincludemulti3つの単語に分けられます:

  • --include=Hello
  • W*.txt
  • --include=*.sh

set -xコマンドの前にスクリプトを追加すると、スクリプトがどのようにgrep実行されるかを正確に確認でき、私が言ったことを確認できます。

+ grep -ERins --include=Hello 'W*.txt' '--include=*.sh' <pattern> <path>

行を変更しincludemulti+=て要素の周りに引用符を追加しても、次のようになります。

includemulti+=" --include=\"$element\""

bashスペースはまだ単語の区切り文字として使用されるため、役に立ちません。

+ grep -ERins '--include="Hello' 'W*.txt"' '--include="*.sh"' <pattern> <path>

ソリューション1

スクリプトを変更しなくてはならない解決策の1つは、要素の周りに引用符を追加することです。そしてevalコマンドの前に組み込みコマンドを追加しますgrepbashマニュアルページから:

評価する[アルギニン...]

これパラメータ読んで一緒に接続してコマンドを形成します。その後、コマンドはシェルから読み取られ実行され、終了ステータスは次のように返されます。評価する。もしなければパラメータ、またはちょうど空のパラメータ、評価する0を返します。

evalしたがって、grepコマンドの前に追加すると、実際には次のようになります。

bash -c 'grep -ERins --include="Hello W*.txt" --include="*.sh" <pattern> <path>'

set -xコマンドの前にはgrep2行が表示され、2行目は実際に実行される行です。

+ eval grep -ERins '--include="Hello' 'W*.txt"' '--include="*.sh"' <pattern> <path>
++ grep -ERins '--include=Hello W*.txt' '--include=*.sh' <pattern> <path>

ソリューション2

これはよりエレガントなソリューションです。繰り返すのではなく、配列変数を変更できますincludearray

# Remove leading space from every element in the array
includearray=("${includearray[@]## }")
# Remove trailing space from every element in the array
includearray=("${includearray[@]%% }")
# Add --include= as the prefix of every element in the array                                                                                                                
includearray=("${includearray[@]/#/--include=}")

その後、grepコマンドは次のようになります。

grep -ERins "${includearray[@]}" <pattern> <path>

includearrayこれにより、配列内の各要素がスペースの数に関係なく単一の単語として扱われるため、要素を引用符で囲む必要がなくなります。

最終コードは次のとおりです。

#!/bin/bash

include="$1"

if [[ $include == *","* ]]; then
    IFS=',' read -r -a includearray <<< "$include"

    # Remove leading space from every element in the array
    includearray=("${includearray[@]## }")
    # Remove trailing space from every element in the array
    includearray=("${includearray[@]%% }")
    # Add --include= as the prefix of every element in the array                                                                                                                
    includearray=("${includearray[@]/#/--include=}")
    
    grep -ERins "${includearray[@]}" "<pattern>" "<path>"
else
    grep -ERins --include="$include" "<pattern>" "<path>"
fi

おすすめ記事