2

与えられた数よりも長い単語の数を画面に出力するように要求する割り当てがあります。たとえば、 k としましょう。これはキーボードから読み取られます。そして、結果を注文します。今まで私はこの方法で試すことにしました:

#!bin/bash
k=0
if [ $# -eq 0 ]
then 
    echo "No argument supplied."
    exit 1
fi
echo -n "Give the minimal lenght of the words : "
read k 
for files in "$@"
do
    if [ -f "$files" ]; then
        echo "$(cat $files | egrep -o '[^ ]{k,}' $files | wc -w) : $files."
    else
        echo "Error: File $files has not been found."
    fi
done | sort -n

私の問題は、「egrep -o '[^]{k,}'」セクションで k を使用してこのプログラムを試すたびに、常に間違った答えが返されることです。しかし、それを整数に置き換えると、 in は思い通りに機能します。キーボードから読み取った k に対してこのコードを機能させる正しい方法はどれですか? これは構文であり、そこにどのように記述すればよいか本当に理解できず、他の方法で "$k" 、 $k 、 ((k)) 、k. どんな助けでも大歓迎です、誰かが私にくれたらヒントをください? ハマった

4

1 に答える 1

1

試す

echo "$(egrep -o '[^ ]{'"$k"',}' "$files" | wc -w): $files"
  • あなたの差し迫った問題は、kの代わりに使用していました$k
    • Bash で変数を参照するには、その名前の前に を付ける必要があります$(対照的に、代入$する場合は使用しないでください)。場合によっては、変数名を後続のトークンから分離するために、名前を で囲む必要があります(例: で囲む必要がある場合でも、視覚的に明確にするためにこれを選択することもできます)。{..}${k}
  • 次の問題は、egrep重引用符を使用して検索正規表現 (コマンド置換内) を区切ることでした。これにより、変数参照の展開が妨げられます。
    • 全体的に二重引用符で囲まれた文字列を使用していたとしても、埋め込まれたコマンド置換 ( $(...)) は独自の世界であり、通常の解析規則が適用されることに注意してください(一重引用符で囲まれた文字列はリテラルですが、二重引用符で囲まれた文字列には変数参照が埋め込まれている場合があります。コマンド置換、算術展開)。
  • ただし、変数参照展開される二重引用符を代わりに使用するだけでは、コマンド置換内の ブレース展開( ) に関連するbash 3.2.57 のバグにより、この場合の問題が解決しない可能性があります。 {...}
    • このバグは bash 4.3.30 にはもう存在しないため (いつ修正されたかは不明) 、二重引用符で囲まれた単一の文字列を使用でき"[^ ]{$k,}"ます。ただし、提示されたソリューションは bash 3.x と 4.x の両方で機能します。
    • 以下は、bash 3.2.57 のバグを示す最小限の例です。
      • k=3; echo "$(egrep -co "[^ ]{$k,}" <<<$'abc\nde')"
      • これは を返すはずですが、二重引用符で囲まれた文字列内に含まれているにもかかわらず、誤ってブレース展開を(結果として2 つの文字列:と) に適用したため、 を1返します。0 2{3,}egrep -co '[^ ]3'egrep -co '[^ ]'
  • したがって、答えは、単一引用符で囲まれた 2 つの文字列の間の変数参照をスプライスすることです。
    • '[^ ]{'"$k"',}'[^ ]{variable$kおよびliteralの値をリテラルに連結します,}。たとえば、$kisの場合、次の文字列が表示されます。4egrep[^ ]{4,}
  • (また、ファイルはオペランド(非オプション引数)としても渡されるため、イニシャルcat $files |は不要でした。また、ファイル名を含む変数は常に二重引用符で囲む必要があるため、スペースが埋め込まれたファイル名でコマンドが壊れることはありません。)
  • 最後に、混乱を避けるために名前を に変更$filesすることをお勧めします。ループの各反復では、 1 つのファイルのみを処理します。$file
于 2015-03-29T23:13:06.017 に答える