2017-07-20 8 views
1

シェルスクリプトは初めてです。私の要件は、2つのパターン間の行を取り出すことです。sed cmd内の変数を使用せずにターミナルから実行すると正常に動作します。しかし、問題は、以下のすべてのものをファイルに入れて実行しようとしたときに発生します。私はターミナルで以下CMDを使用している場合SEDコマンド内の変数を使用して2つのパターンの間の行を選択してください

#!/bin/sh 
word="ajp-qdcls2228.us.qdx.com%2F156.30.35.204-8009-34" 
upto="2017-01-03 23:00" 
fileC=`cat test.log` 
output=`echo $fileC | sed -e "n/\$word/$upto/p"` 
printf '%s\n' "$output" 

はそれが

sed -n '/ajp-qdcls2228.us.qdx.com%2F156.30.35.204-8009-34/,/2017-01-03 23:00/ p' test.log 

回避策を提案してください正常に動作します。

+0

あなたが本当にうまく動作すると言うコマンドは、アンカーがなく、regexpメタキャラクタとバックリファレンスのエスケープが原因で、入力ファイルの内容が誤って一致して実際に失敗します。 **本当に** sedでこれをやりたいのであれば、https://stackoverflow.com/a/29626460/1745001を参照してください。もちろん、代わりに文字列マッチングのためにawkを使用するほうがはるかに良いでしょう。正規表現マッチングの正しい方法でこれを行う方法についてのヘルプが必要な場合は、簡潔でテスト可能なサンプル入力と期待される出力を表示するために質問を編集してください。 –

答えて

2

私たちは、あなたがファイルを引用していないので、あなたのコマンドが動作しない理由がある、sedフィルタリングのためにそれを変数に一瞬のために取って、あなたがすべきではないcatファイル事実を配置し、echo場合コンテンツ変数、 echo ing。これは、複数の空白文字をまとめて1つのスペースに変換します。だから、あなたはそれを修正するファイルから失う改行、などなど、複数のスペース、タブ、

している、あなたが書くことができます。

fileC=$(cat test.log) 
output=$(echo "$fileC" | sed -n "/$word/,/$upto/p") 

は(fileCの周りに二重引用符に注意してください。固定式のsedという2つ目の例と似ています)。引用符を使用しないと(echo $fileCを試してください)、が一連の単語に展開され(IFS)、それぞれechoの1つの引数となり、echoは単一のスペースで区切られた単語を出力します。さらに、ファイルにグロブリング文字の一部(*など)が含まれている場合、それらのパターンも展開されます。これはcommon bash pitfallです。

output=$(sed -n "/$word/,/$upto/p" test.log) 

そして、あなたのパターンはsedメタ文字の一部が含まれている場合、あなたが本当にescape themこのように、sedで使用する前にすべきである:

escape() { 
    sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"$1"; 
} 
output=$(sed -n "/$(escape "$word")/,/$(escape "$upto")/ p" test.log) 

がはるかに良い、このようにそれを書くことだろう

+1

魅力的な作品 –

1

正しいアプローチは次のようになります。

word="ajp-qdcls2228.us.qdx.com%2F156.30.35.204-8009-34" 
upto="2017-01-03 23:00" 
awk -v beg="$word" -v end="$upto" '$0==beg{f=1} f{print; if ($0==end) exit}' file 

サンプル入力と出力が表示されるまでは、一致する必要があるもの(フルライン、部分ライン、1行のすべてのテキストなど)または印刷するものがわからない(区切り文字を含む、除外する、除外するなど)。