빈 줄이 있을 수 있는 파일 입력이 있는데 빈 줄을 건너뛰고 싶습니다.
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
-r
xargs
( 어쨌든 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
-d
xargs
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가 충돌하는 인수이며 후자가 우선합니다.