나는 이와 같은 bash 스크립트를 가지고 있습니다
export pipedargument="| sort -n"
ls $pipedargument
하지만 오류가 발생합니다.
ls: |: No such file or directory
ls: sort: No such file or directory
"| sort -n"
내용을 에 전달된 매개변수 로 취급하는 것 같습니다 ls
.
일반 파이프 명령처럼 처리되도록 어떻게 이스케이프 처리합니까?
이것을 조건부로 설정하려고 합니다 $pipedargument
. 조건부로 다른 버전의 명령을 실행할 수 있을 것 같지만 위와 같이 작동하도록 할 수 있는 방법이 있는지 궁금합니다.
답변1
|
당신 말이 맞아요, 이렇게 하면 안 돼요 . 그 이유는 쉘이 변수 대체를 수행하기 전에 이미 파이프를 찾아 명령으로 분할하기 때문입니다. 따라서 |
그냥 또 다른 캐릭터로 간주됩니다.
한 가지 가능한 해결 방법은 파이프 문자를 문자 그대로 배치하는 것입니다.
$ cmd="sort -n"
$ ls | $cmd
cat
파이프가 필요하지 않은 경우 "nop" 또는 자리 표시자로 사용할 수 있습니다 .
$ cmd=cat
$ ls | $cmd
이 방법은평가의 미묘함. 당신은 또한 볼 수 있습니다여기.
더 나은 접근 방식: 배열
보다 정교한 접근 방식은 bash
일반 문자열 대신 배열을 사용하는 것입니다.
$ cmd=(sort -n)
$ ls | "${cmd[@]}"
cmd
인용된 인수를 포함하는 명령이 필요할 때 배열의 장점이 중요해집니다.
답변2
eval
다음 명령을 사용할 수 있습니다 .
eval "ls $pipedargument"
또는 다음과 같이 함수를 정의하는 것이 더 좋습니다.
sorted() { "$@" | sort -n; }
그런 다음 필수 매개변수를 사용하여 호출하세요.
sorted ls /tmp
답변3
나는 이것을 위해 함수를 사용할 것입니다. 그것은 다음과 같습니다:
### usage pipedargument cmd args ###
pipedargument()
{
sort -n <<< "$( "$@" )"
}
$ pipedargument /sbin/ifconfig eth0
RX bytes:5904986765 (5.4 GiB) TX bytes:714370767 (681.2 MiB)
RX packets:5981427 errors:0 dropped:0 overruns:0 frame:0
TX packets:4403989 errors:0 dropped:0 overruns:0 carrier:0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
collisions:0 txqueuelen:1000
inet addr:XXX.XXX.X.XX Bcast:XXX.XXX.X.XXX Mask:255.255.255.0
inet6 addr: xx00::0x0x:00xx:xx0:000/00 Scope:Link
eth0 Link encap:Ethernet HWaddr 0x:0x:00:x0:00:00