パイプライン入力ラインごとに1回コマンドを実行しますか?

パイプライン入力ラインごとに1回コマンドを実行しますか?

各一致に対してJavaコマンドを1回実行したいと思いますls | grep pattern -。この場合はできると思いますが、find pattern -exec java MyProg '{}' \;一般的なケースが気になります。 「標準入力の各行に対して一度だけコマンドを実行する」と言う簡単な方法はありますか? (魚やバッシュから。)

答え1

受け入れられた回答アイデアは正しいが、鍵はxargsスイッチを通過する-n1ことです。「コマンドラインごとに最大1つの引数を使用してください。」:

cat file... | xargs -n1 command

あるいは、単一の入力ファイルの場合、catパイピングをすべて回避し、次のものを使用できます。

<file xargs -n1 command

2020年8月5日に更新:

私はまたユーザーJanderの意見の提供に答えたいと思います。この提案は、いくつかの誤った情報が含まれているにもかかわらず、よく支持されています。これについては今説明します。

(主張されている)問題に言及せず、-Lオプションを推薦するために急がないでください。xargs末尾の空白関数引き起こす可能性があります。私の考えでは、これらの変化は得よりも糸が多いでしょう-L 1一度に1つの空でない行で動作。公平に言えば、マニュアルページはxargs明確です。特徴(つまり問題)はスイッチに付属しています-L

Janderは、コメントや回答を福音として受け入れるのではなく、マニュアルページを読むのと同じくらい退屈な仕事をする時間がなかった、急いで疑わしいStackOverflowの聴衆にクイックヒントを求めるときにこれらの問題に言及しなかったので、その-L問題に対処します。今私の推論は、-L旅行中に持って行くすべての手荷物を詳しく見ていないことが非常に悪いアドバイスであるということです。

私の軽蔑を説明するために、-L誰か(おそらく訓練中にこのデータファイルを作成した高校の夏のインターン)が誤って入力し、テキストを含む単純な入力ファイルを考えてみましょう。証拠は次のとおりです。ウィンドウタイプファイル名。幸いにも(カルマ?)経営陣によってあなたが新しい管理人に選ばれました。

testdata.txt

1
2␠
3

数字を含む行に空白文字があるため(ブラウザのフォントにその文字が視覚的に表示されない場合は、2前のコードでSYMBOL FOR SPACE数字の後にUnicode文字として表示されます)、コマンドは次のように使用します。2xargs -L1

<testdata.txt xargs -L1 echo

...、次のような(おそらく驚くべき)出力が生成されます。

1
2 3

-Lこれはスイッチディレクティブによるものです。xargsスペースで終わる行に次の行を追加します。この動作は、末尾の空白のために行が正しく切り取られない奇妙な瞬間の結果出力にのみ影響を与える可能性があります。正しい入力ファイルが表示されるのを待つ時限爆弾エラーです。

一方、スイッチを使用する同じコマンドは、より-n 1許容可能な出力を生成します。xargs-L 1

1
2␠
3

それは最悪ではありません! 「怖い」オプションを強制する代わりに、この-Lスイッチを使用してください。これにより、実行中の環境に比べて長すぎると思われるコマンドラインが見つかると、プロセスは終了します。-n-xxargsxargs

スイッチの指示に従って、末尾の空白を含む連続した複数行の入力ファイルと混合物で「エージェント」と呼ばれる化学試薬を使用している-L場合、それらすべてが1つに接続されていると中間ストリームのシャットダウンが発生する可能性があります。-xxargsスーパーラインxargs'という定義を超えて行が長すぎます。コマンドラインの場合。状況が曇り始めたら、次の点を考慮してください。行が長すぎます。xargs実行中のプラットフォームに指定された最大長に基づいてサイズが決定され、見かけによる追加のオフセットによって決定されます。任意の定数マンページで詳しく説明します。面倒な否定積分と微積分学の原理を覚えていますか?任意の定数+ C否定積分の年を書くのを忘れたので、クイズや試験で得点を失いましたか?まあ、これを-Lあなたの便利なツールボックスに追加するとxargs、その言葉が再びあなたの背中を噛むでしょう。

一方、Value-nはこれらの長い行を小さな一口サイズの1行の塊に切り取り、空白で終わるかどうかにかかわらず、各塊に与えられたコマンドを一度に1つずつ実行します。もはや長いキューがなくなり、もはや突然終了し、後ろから突くことはありません。 Et tu, Brute ?1xargsxargs -x

xargs のマニュアルページのフレーズのオプション Segue

なぜ表現があいまいで不規則なのかわかりません。スペースxargs次のように、より明確に定義され、あいまいなオプションではなく、マニュアルページ全体で使用されます。

  • スペースがある場合スペース1つ以上を示します。ASCIIスペース数値
  • 改行以外の空白(該当する場合)スペースヒント)
  • グループに印刷できない文字が1つ以上あります。{スペース、水平タブ}(もしスペースこの恐ろしいデュオの同義語として使用されます)

2021年6月15日に更新:

@BjornWユーザーがxargsコマンドごとに1回コマンドを実行する方法を尋ねました。ワイヤー単に入力された単語ではなく、入力された内容です。 (私はコメントを読み、コロナ19に対応するのに7ヶ月かかったことを非難するしかありません:P)。

元の質問の精神に基づいて、私の答えをより多くのユースケースに適用できるように、この特定のシナリオについて詳しく説明します。

次の入力ファイルを検討してください。実際の業務に触れることができる様々なEdge Caseがいっぱいです。現実世界™(例:先行/末尾の空白、空白のみで構成される行、空行、ハイフンで始まる行[スイッチを導入すると解釈してはいけません]など):

lines.txt

a1 a22 a333 a4444
b4444 b333 b22 b1
␠␠c d e f g
hhh
ii jj kk␠
␠␠␠
-L and -x are the gruesome twosome

以前の入力ファイルでは、OPEN BOX空白行を表示するためにUnicode文字U + 2423を使用し、前後のSYMBOL FOR SPACEスペースをより引き立てるためにUnicodeを使用しました。

内容に関係なく(内容なしを含む)、全体として取り出され、単一の引数でコマンドに渡される各入力行でコマンドを実行するとします。xargs以下のようにこれを行います(注:コマンドprintf例となり、%q書式指定子を使用して指定された引数が空白の場合、または引数が空の文字列の場合は明確にするためにアポストロフィで囲みます。すべて入力、入力のみ可能hhh) "unscathed "行、%q出力に見られるように印刷できない文字がある場合は、%qPOSIX$''引用構文を使用してエスケープされます。]):

<lines.txt xargs -n1 -d'\n' printf -- 'Input line: %q\n'

出力は次のとおりです。

Input line: 'a1 a22 a333 a4444'
Input line: 'b4444 b333 b22 b1'
Input line: '   c d e f g'
Input line: ''
Input line: hhh
Input line: 'ii jj kk '
Input line: ''
Input line: '   '
Input line: '-L and -x are the gruesome twosome'
Input line: ''
Input line: ''
Input line: ''

だからそこにあります。このスイッチを使用すると、引数が終了し、次の引数が始まる場所を示すために-d入力ファイルで見つける必要がある区切り文字を指定できます。それ自体で十分にスマートにxargs設定すると、次のように解釈できます。'\n'xargsCスタイル文字エスケープ-dそのページのスイッチの説明に記載されているように、manこれを使用してxargs最小限の労力で入力行全体を選択したコマンドの引数として渡すことができます。

xargsまた、この動作が必要なまれなケースに対して複数の入力行を接続し(この段落の最後で詳しく説明する注意事項とともに)、次のように渡すために使用できることにも触れたいと思います。私たちのコマンドの単一引数です。上記の呼び出しコマンドで-nスイッチに渡された数値を、プロセスから行末が削除された単一の引数xargsにマージする必要がある入力行数を示す値に設定するだけです。\n残念ながら、これらの改行除去動作は、上記のアプローチをxargs多くのユースケースに適さないようにする。これは、1行が終了し、次の行が始まる場所を示す情報がプロセスから失われるためです。

答え2

Bashまたは他のBourneスタイルのシェル(ash、ksh、zshなど)から:

while read -r line; do command "$line"; done

read -r標準入力から1行を読みます(バックスラッシュは解釈さreadれないので-r望ましくありません)。したがって、次のいずれかを実行できます。

$ command | while read -r line; do command "$line"; done  

$ while read -r line; do command "$line"; done <file

答え3

それだけですxargs

... | xargs command

答え4

GNU Parallel はこれらの作業のために設計されています。最も簡単な使い方は次のとおりです。

cat stuff | grep pattern | parallel java MyProg

詳しくは、紹介ビデオをご覧ください。http://www.youtube.com/watch?v=OpaiGYxkSuQ

関連情報