xargs は -d'\n' を使用する場合は空行を無視します。

xargs は -d'\n' を使用する場合は空行を無視します。

空行を持つことができるファイル入力がありますが、空行をスキップしたいと思います。
grep /trを使用し、出力をxargsにパイピングする必要がないソリューションを見つけようとしています。

次のxargオプションを使用してください

-アル字型引数なしでコマンドを実行したくありません。 -d '\n'新しい行は区切り記号です。

echo コマンドを使用します。

echo "" | xargs -r -d'\n' -I {}  echo "test '{}'"

出力:

test ''

空行で構成されたファイルを使用するコマンド:

xargs -a /tmp/test.txt -r -d'\n' -I {}  echo "test '{}'"

出力:

test ''
test ''
test ''

上記のようにgrepを使用できますが、xargsのみを使用して実行できるかどうか疑問に思います。

grepの例(動作中):

grep -v -e '^$' /tmp/test.txt | xargs -r -d'\n' -I {}  echo "test '{}'"

答え1

-r-I空の要素を無視する代わりに、入力に要素がないときにコマンドを一度実行しないでください(BSDではありませんが)-J。必須ではありません。

あなたは通常-rこの理由でそれをしたいです。

find . -criteria -print0 | xargs -0 ls -ld

何も見つからない場合は、引数なしで実行さfindれ、ls -d表示されます.

だからあなたは欲しい:

find . -criteria -print0 | xargs -r0 ls -ld

何も見つからないとlsまったく実行されませんfind

と両方ともGNU拡張-rです(再び、移植性が低下します)。 FreeBSD と NetBSD を含む一部の BSD のデフォルト動作です (これは POSIX と互換性がありませんが)。-0-d-rxargs

(とにかくxargs特定の例ではあなたのものと同じである必要はありませんfind . -criteria -exec ls -ld {} +)。

私が知る限り、GNUはオプションをサポートするxargs唯一の-d実装であり、nullかどうかにかかわらず、特定のパラメータ値のフィルタリングをサポートしていないのでgrepgrep -v '^$'またはLC_ALL=C grep .)を使用するのが正しいアプローチです。

-aたとえば、コマンドのstdinを変更せずにkshスタイルのプロセス置換(ksh、zsh、bash)をサポートするシェルを使用するなど、他のGNU拡張機能を引き続き使用したい場合は、次のようにします。

xargs -rd '\n' -a <(grep -v '^$' test.txt) cmd --
xargs -d '\n' -I{} -a <(grep -v '^$' test.txt) cmd -- {}

(rc、akanga、es、fish、yashシェルは機能は同じですが構文は異なります)。

-0のよう-d '\0'なので衝突することに注意してください-d '\n'd希望のリミッターを選択してください。後者が-0 -d '\n'最後なので優先順位があります。

-0コマンドパラメーターまたはファイルパスには現れないシングルバイト値であるため、好ましい区切り文字です。-0、現在他の多くの実装(ほとんどのBSD、Solaris、busybox、toybox、ast-open実装を含む)-dに見られるものとは対照的です。サポートされていない実装(つまり、GNUを除くすべての実装)xargsの場合は、次のものを使用できます。xargs-dxargs

tr '\n' '\0' | xargs -0 ...

GNUの代わりに:

xargs -d '\n' ...

を使用している場合は、使用する代わりzshに、xargs次のことができます。

for arg ( ${(f)"$(<test.txt)"} ) cmd -- $arg

パラメータf拡張フラグは改行に分割され、${...}引用符がないため空の要素が削除されます。

そしてbash

readarray -t args < test.txt &&
  for arg in "${args[@]}"; do
    [ -z "$arg" ] || cmd -- "$arg"
  done

引用符なしの配列拡張機能を使用してヌル削除を実行することもできますが、引用符なしの引数拡張機能によっても実行されるワイルドカードと分割を無効にする必要があります。

IFS=; set -o noglob
readarray -t args < test.txt &&
  for arg in ${args[@]}; do
    cmd -- "$arg"
  done

次のこともできます。

while IFS= read <&3 -r arg || [ -n "$arg" ]; do
  [ -z "$arg" ] || cmd -- "$arg" 3<&-
done 3< test.txt

これは標準sh構文です。

答え2

-0'他のキャラクターと一緒に逃げたくなかったです。
-r空行を無視したいです。
-d '\n'新しい行は区切り記号です。

-0との組み合わせは-d '\n'私には理解できないようです。 NULバイトを区切り文字として使用し、改行文字を区切り文字として使用するように指示します-0。両方とも引用符とバックスラッシュ処理を無効にします。xargs-d '\n'

-0--null
項目は空白ではなくNULL文字で終わり、引用符とバックスラッシュは特別ではありません(各文字は文字通り使用されます)。 [...]

--delimiter=delim-d delim

入力用語は指定された文字で終わります。 [...]入力を処理するときの引用符とバックスラッシュは特別ではありません。入力のすべての文字は文字通り処理されます。 [...]

私が見つけたGNUのバージョンによると、両方が提供された場合、後者が適用されるようです。たとえば、次のようになります。

$ printf 'foo\nbar\n' | xargs -0 -d'\n' -I {}  echo "<{}>"
<foo>
<bar>
$ printf 'foo\nbar\n' | xargs -d'\n' -0 -I {}  echo "<{}>"
<foo
bar
>

入力に空の要素が含まれていて使用する場合は、またはNULで区切られた値を介してパイプするだけですxargs。 (またはバイトシーケンスのみを含む行を許可する必要がある場合grep .grep -z .grep -v '^$'いいえ現在のロケールで有効な文字を形成します。 )

フィルタラインはとにかく意味があり、grepすでにxargs別々のプロセスに分岐しているので、フィルタラインを追加してもgrep大きな違いはありません。また、必要に応じてスペースのみを含む行を削除するなど、正規表現を簡単に変更できます。

答え3

grep(または他のツール)を使用し、出力をxargsにパイプして空の入力をフィルタリングする必要があることを確認するために、私の質問に答えます。

解決策:

grep -v '^$' /tmp/test.txt | xargs -r -d'\n' -I {}  echo "test '{}'"

Stéphane Chazelasが明らかにしたように、-rは空の入力をフィルタリングしませんが、入力がないときに実行を防ぎます。

xargsのマニュアルページ-r、--no-run-if-emptyセクションで:
通常、コマンドは入力がなくても一度だけ実行されます。

追加編集では、追加の注意点は-0と-dが競合する引数であり、後者が優先します。

関連情報