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이든 아니든 특정 매개변수 값 필터링을 지원하지 않으므로 grep( grep -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

따옴표가 없는 배열 확장을 통해 null 제거를 수행할 수도 있지만, 따옴표가 없는 인수 확장을 통해서도 수행되는 와일드카드 및 분할을 비활성화해야 합니다.

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
항목은 공백이 아닌 널 문자로 종료되며 따옴표와 백슬래시는 특별하지 않습니다(각 문자는 문자 그대로 사용됩니다). [...]

--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가 충돌하는 인수이며 후자가 우선합니다.

관련 정보