2016-11-04 36 views
0

fgrep文をファイルから完全一致のレコードで削除しようとしています。私はコマンドラインでこれを行うことができますが、kshスクリプト内ではできません。私が使用していたコードは、コードのこれらの4つのラインに沸く:kshスクリプト内のスペースを含む文字列を含むfgrep

Header='abc def|ghi jkl' #I use the head command to populate this variable 

    workfile=abc.txt 

    command="fgrep -Fxv \'$Header\' $workfile" >$outfile 

    $command 

私はSTDINに$commandをechoコマンドは、私が(単一引用符で)コマンドラインに入力しますまさにであり、それは上で動作しますコマンドライン。 kshスクリプト(ファイル)内で実行すると、エラーがスペース上で解析されているため、一重引用符は認識されないようです。

$command変数を使用せずに、ダニックス、エグゼクティブ、eval、一重引用符ではなく二重引用符を試しました。問題は残っている。

+3

人が '$ cmd'変数を構築しようとするときに、通常はシェルが別の経路で解決できる何かをしようとしているからです。あなたは本当に '$ command'を実行する必要がありますか?私は、通常のシェルスクリプトを動作させるためにあなたの努力を集中させて、この余分な間接レベルが本当に必要かどうかを決定します。そして '$ header'の' | 'charについては不明です。 grep reg exでは、これは 'OR'を表します。もちろんシェルでは 'パイプ'です。ここでいくつかの問題は明確ではありません。あなたのQを更新してください(またはこの問題のための戦術を変更してください)。がんばろう。 – shellter

+0

答えがあなたの問題を解決する場合は、その横にある大きいチェックマーク(✓)をクリックして受諾し、オプションで上向きに投票してください(上向き投票には少なくとも15の評判ポイントが必要です)。 他の回答が有益だった場合は、投票してください。受諾およびアップ投票は将来の読者に役立ちます。関連するヘルプセンターの記事(http://stackoverflow.com/help/someone-answers)を参照してください。質問にまだ完全に回答していない場合は、フィードバックを提供してください。最高の解決策を自分で見つけたと感じたら、それを回答として投稿し、自己受け入れます。 – mklement0

答えて

1

Bash FAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!は、包括的なガイダンスを提供します - それはバッシュのために書かれている間、そのほとんどが同様にKshをに適用されます。 [1]

あなたはあなたのコマンドを保存するに固執したい場合は、引用問題迂回配列、使用(がより良い選択である機能定義)変数

#!/usr/bin/env ksh 

Header='abc def|ghi jkl' 

workfile=abc.txt 

# Store command and arguments as elements of an array 
command=('fgrep' '-Fxv' "$Header" "$workfile") 

# Invoke the array as a command. 
"${command[@]}" > "$outfile" 

注のみ単純コマンドは、配列に格納することができ、それの一部にすることはできませんリダイレクション。


[1]の実施例は、サポートされていないkshローカル変数を作成するlocalを使用する機能。代わりにlocalをシェルグローバル変数で行うか、localの代わりにtypesetの代わりにfunction <name> {...}の構文を使用して、kshにローカル変数を宣言してください。

2

私は、コマンドラインでこれを行うことができますが、ないkshのスクリプト内の

ここヒアドキュメントを使用して、簡単な、ポータブル、信頼性の高いソリューションです。

#!/usr/bin/env ksh 

workfile=abc.txt 
outfile=out.txt 

IFS= read -r Header <<'EOF' 
abc def|ghi jul 
EOF 

IFS= read -r command <<'EOF' 
grep -Fxv "$Header" "$workfile" > "$outfile" 
EOF 

eval "$command" 

説明

(彼らはヒアドキュメントの行に影響を与えるので、コメントは上記のスクリプトに追加することはできません)

IFS= read -r Header <<'EOF'     # Line separated literal strings 
abc def|ghi jul        # Set into the $Header variable 
EOF           # As if it were a text file 

IFS= read -r command <<'EOF'     # Command to execute 
grep -Fxv "$Header" "$workfile" > "$outfile" # As if it were typed into 
EOF           # the shell command line 

eval "$command"        # Execute the command 

上記の例は、というテキストファイルを持つのと同じですヘッダー。abc def|ghi jul、次のコマンドを入力:

  • grep -Fxvf header.txt abc.txt

ヒアドキュメントアドレスの結果として、異なるコマンドラインよりも操作するスクリプトの問題内容を含むTXT引用/拡張/エスケープの問題。 evalに関する注意の

Aワード:

この例でevalの使用が特異的です。 evalが悪用され、非常に危険な結果をもたらす可能性のある情報については、Eval command and security issuesを参照してください。


詳細/代替例:完全性、明確性、および他の状況にこの概念を適用する機能性のために

ヒアドキュメントと代替デモに関するいくつかの注意事項:

この例では

ヒアドキュメントのこの実装がSPでありますecifically以下の基準で設計:評価し、実行するevalコマンドの

  • 内容のリテラル文字列代入、変数に'EOF'を使用して)
  • 使用heredoc自体の内部で参照される変数。

ファイルやヒアドキュメント? のgrepの-Ffgrep)と組み合わせヒアドキュメントを用いる

一つ強度は、それがファイルであるかのようにスクリプトの部分を治療する能力です。ファイルの

ケース:

  • あなたが頻繁にファイルに「パターン」の行を貼り付け、なしは、スクリプトファイルを変更すること、必要に応じてそれらを削除したいです。ヒアドキュメントのための

ケース:

  • あなたは、特定のファイルが既に存在している環境でスクリプトを適用し、それに対する具体的な正確なリテラルのパターンにマッチします。

例:

  • シナリオ:私は5つのVPSサーバーを持っている、と私はスクリプトが、それは正確なラインが含まれていないことを確認するために、新しいfstabファイルが、を生成します:
  • /dev/xvda1 /    ext3 errors=remount-ro,noatime,barrier=0 0  1

このシナリオは、この問題で対処される状況に適しています。私はこの答えでは上記のコードから定型を使用して、次のように変更できます。

#!/usr/bin/env ksh 

workfile=/etc/fstab 

IFS= read -r Header <<'EOF' 
/dev/xvda1/    ext3 errors=remount-ro,noatime,barrier=0 0  1 
EOF 

IFS= read -r command <<'EOF' 
grep -Fxv "$Header" "$workfile" 
EOF 

eval "$command" 

これはヒアドキュメントに含まれる行せずに、私に新しいfstabファイルを与えるだろう。

+0

FYI - eval、execこれらは機能しません。私は解決策を見つけた。 -fまたは--fileオプションを指定してfgrepを呼び出します。指定したファイルに一致文字列を入れることができます。その文字列には、スペース、一重引用符、二重引用符などを含めることができます。 – Norah

+0

これは良いことです。達成しようとしていることを明確にする必要があります。 - コマンド変数を具体的に使用したいのか、fgrepを機能させたいのかは明確ではありませんでした。 – hmedia1

+1

あなたのhere-docソリューションは堅牢ですが、まだそれを宣伝しません。なぜなら、 'eval'の完全な意味を理解するのは一般的に難しいからです。これとは対照的に、最初の解決策は堅牢ではありません。削除することをお勧めします(例えば、 'Header =" a'b "'を試してみてください)。 – mklement0

関連する問題