이것은 실제로brew search
하지만 단순화를 위해 다음과 같이 한다고 가정하겠습니다.
echo -e 'somedir\n\otherdir'
somedir
otherdir
otherdir
이렇게 하지 않고 매개변수로 사용할 수 있나요 ?
ls $(echo -e 'somedir\n\otherdir |tail -n1)
otherdir
목표를 명확히 하기 위해 업데이트됨
더 명확하게 somedir
하고 otherdir
stdout으로 가려면 그냥 할 수 있습니다.otherdir
출력을 캡처한 $()
다음 이에 대해 명령을 실행하지 않습니까?
나는 이것이 가능하다고 생각하지만 그것이 가능하다고 생각하지 않는지 궁금합니다.
답변1
다음을 사용하여 언제든지 xargs
출력 스트림을 매개변수 목록으로 변환할 수 있습니다.
printf 'somedir\n\otherdir\n' |
tail -n1 |
xargs -rd '\n' ls -l --
-d '\n'
행에 GNU 구현이 필요하기 때문에 여기에는 인수가 필요 합니다 xargs
.
마지막 줄에 공백, 따옴표, 백슬래시가 없으면 생략할 수 있습니다.
-r
ls
입력이 비어 있으면 실행을 피해야 하는 , 역시 GNU 에서 왔지만 xargs
현재는 널리 지원됩니다(그리고 POSIX 표준의 다음 버전에 나타날 예정입니다).
명령 대체를 사용하지 않으려면 bash
언제든지 명령 출력 줄을 배열로 읽어 배열의 마지막 요소에서 명령을 실행할 수 있습니다.
readarray -t lines < <(printf 'somedir\notherdir\n')
if (( ${#lines[@]} > 0 )); then
ls -l -- "${line[@]: -1}"
fi
또는 다음을 사용하십시오 perl
.
printf 'somedir\notherdir\n' |
perl -lne 'exec qw(ls -l --), $_ if eof && $.'
명령 대체를 사용하면 모든 후행 줄 바꿈이 제거되므로 빈 입력과 빈 마지막 줄을 직접 구별할 수 없습니다. 두 경우 모두 확장을 얻고 비워지게 됩니다.
명령 대체 사용의 장점 중 하나는 출력 사용을 결정하기 전에 명령이 성공했는지(종료 상태를 기준으로) 확인할 수 있다는 것입니다.
die() { [ "$#" -eq 0 ] || printf>&2 '%s\n' "$@"; exit 1; }
last_line=$(
set -o pipefail
cmd | tail -n 1
) || die "cmd failed"
ls -l -- "$last_line"
또는 grep
이를 사용하여 출력이 비어 있지 않은지 확인할 수도 있습니다.
if
last_line=$(
set -o pipefail
cmd |
tail -n 1 |
grep '^'
)
then
ls -l -- "$last_line"
else
echo>&2 "Either cmd failed or it didn't produce any output"
fi
grep '^'
줄의 시작 부분과 일치합니다. 따라서 출력에 하나 이상의 행이 포함되어 있으면(비어 있는지 여부에 관계없이) true를 반환합니다. 그러나 입력이 개행으로 끝나지 않으면 POSIX 줄 정의에 따라 줄로 간주되지 않으며 grep
이 경우 일부 구현이 실패하거나 구분되지 않은 줄을 삭제할 수도 있습니다.
답변2
문법 $()
번호구하다아무것. 이는 기본적으로 "이 명령을 실행하고 출력을 인수로 사용한다"는 의미입니다.
귀하의 사용법은 올바른 표준 작업 방식입니다.
(여전히 작동하는) 이전 쉘에서는 백틱(`)이 다음과 같이 작동합니다.
하지만 이는 $()
현대적인 방식이며, 기존 방식이 갖고 있던 까다로운 참조 문제도 많이 해결해 줍니다.
예를 들어 거의 모든 곳에서 사용할 수 있습니다.
echo "The current time is: $(date)"
The current time is: Tue Nov 21 22:57:41 EST 2023