별칭 없이 변수에 명령 할당

별칭 없이 변수에 명령 할당

우연히 bash에서 alias.

g=date
$g
Mon Jun 27 13:00:40 MYT 2016

작동합니다. 또 다른 예는 다음과 같습니다.

jj="ping yahoo.com"
$jj
PING yahoo.com (98.138.253.109) 56(84) bytes of data.
64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=1 ttl=41 time=347 ms
64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=2 ttl=41 time=345 ms
64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=3 ttl=41 time=345 ms

이 버전의 bash를 사용하고 있습니다bash --version GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

나는 조사했다스택교환그리고TLDP 복근, 하지만 우리가 이렇게 할 수 있다는 것을 찾지 못했습니다. 그렇다면 이것이 bash의 새로운 기능인가요, 아니면 간과되고 있는 것인가요? 이것이 고려되는가명령 대체?

답변1

대화형 사용 시 쉘은 터미널 장치에서 입력 행을 읽습니다. 한 줄을 입력한 후에는 다음과 같습니다.파싱된으로 분할하여토큰(단어 및 연산자). 그러면 토큰이나 단어가 특정 순서로 확장되거나 해결됩니다.

참고: 일반적으로 고급 Bash 스크립팅 가이드, 온라인 튜토리얼, 책, 심지어 Stack Exchange :)와 같은 중고 소스보다 프로젝트 문서나 산업 사양과 ​​같은 정식 정보 소스를 참조하는 것이 가장 좋습니다. 이러한 중고 소스는 개념을 더 간단한 언어로 소개하고 설명하는 데 유용하지만 일반적으로 공식 문서를 완전하게 만들거나 대체하기 위한 것은 아닙니다. 중고 자료의 정보도 최신 정보가 아닐 수 있습니다.

이 경우,단순 명령 구문 분석을 위한 POSIX 사양다음과 같이 말합니다

  1. 변수 할당이나 방향 재지정이 아닌 단어는 확장되어야 합니다. 확장 후에도 필드가 남아 있는 경우 첫 번째 필드는 명령 이름으로 간주되고 나머지 필드는 명령에 대한 인수로 간주됩니다.

그만큼간단한 명령 확장에 대한 Bash 매뉴얼 섹션또한 다음과 같이 말합니다.

  1. 변수 할당이나 리디렉션이 아닌 단어는 확장됩니다(쉘 확장 참조). 확장 후에도 단어가 남아 있으면 첫 번째 단어가 명령 이름으로 사용되고 나머지 단어는 인수로 사용됩니다.

답변2

이것은 명령 대체가 아닙니다.변하기 쉬운치환. 변수에 명령을 할당하는 것이 아니라 문자열을 할당하는 것입니다. 명령은 할당 시점이 아니라 변수를 사용할 때 실행됩니다.

g=date문자열을 date변수에 저장합니다 g. 그런 다음 를 실행하면 echo "$g"의 값이 인쇄됩니다 g( date뒤에 개행 문자가 표시됨). 왜냐하면 의 값이 첫 번째 인수로 명령 g에 전달되기 때문입니다. echo를 실행하면 "$g"문자열이 date명령의 첫 번째 위치에 배치되므로 이것이 명령 이름이 됩니다.

에서는 $jj두 번째 요소가 작용합니다. 변수 확장이 따옴표 바깥에 있기 때문에"분할+글로브 연산자"값에 적용됩니다. 이 경우 이는 값이 jj공백으로 구분된 두 단어로 분할됨을 의미합니다. 따라서 단어는 ping명령 위치로 끝나고 해당 단어는 yahoo.com첫 번째 인수가 됩니다.

답변3

이는 예상되는 동작이며 오랫동안 작동해 왔습니다. 스크립트에서 명령을 작성하는 데 유용합니다.

예를 들어, 일부 입력을 파이프라인으로 보내기 전에 압축 해제를 적용해야 하는 경우도 있지만(나중에 출력에 압축을 적용해야 하는 경우도 있지만) 그렇지 않은 경우도 있습니다. 사용 bash:

if (( use_compression == 1 )); then
   infilter='gzip -d -c'
   outfilter='gzip -c'
else
   infilter='cat'
   outfilter='cat'
fi

$infilter "$indatafile" | somepipeline | $outfilter >"$outdatafile"

명령 대체입니까? 아니요. "명령 대체"는 특히 $(...)백틱 변형을 출력 내용으로 대체하는 것을 의미합니다.

대신에 이것은매개변수 확장즉, 단순히 매개변수를 해당 값으로 바꾸는 것입니다. 이는 명령이 실제로 실행되기 전에 발생하므로 작동합니다.

이는 다음과 같은 내용이 명령줄에서도 작동한다는 것을 의미합니다.

$ decompress='gzip -d -c'
$ ${decompress/g/gun/} filename >unzippedfilename

( gunzip대신 실행됩니다 gzip)

편집하다:별칭 정보.

설명서 bash에는 다음과 같이 나와 있습니다.

거의 모든 목적에서 별칭은 셸 함수로 대체됩니다.

... 동의합니다.

별칭은 다음과 같은 짧은 작업에 적합합니다.

alias ls="ls -F"

(이것은 내 쉘 세션에서 가지고 있는 유일한 별칭입니다)

명령줄에서 "별칭 지정" 명령을 위해 매개변수 확장을 사용하고 싶지 않을 수도 있습니다. 다른 이유가 아니라면 타이핑하는 데 목이 아프기 때문입니다. 또한 매개변수 확장은 파이프라이닝과 같은 약간 더 복잡한 작업을 수행하는 것을 허용하지 않습니다.

정기적으로 수행하는 다소 복잡한 작업이 있는 경우에는 대신 셸 기능을 사용하세요.

허용되는 답변의 예를 들면 다음과 같습니다.U&L 질문(아래 댓글에 링크되어 있습니다):

alias my_File='ls -f | grep -v /'

이 별칭은 분명히 작동하지만

my_File='ls -f | grep -v /'

$my_File그런 다음 명령줄에서 명령으로 사용하려고 하면 작동하지 않습니다 (해당 U&L 스레드에서 설명된 이유).

쉘 함수를 사용하면 인수 전달과 같은 작업도 수행할 수 있습니다.

function my_File {
    ls -l "$@" | fgrep -v '/'
}

$ my_File -iF symlink
84416642 lrwxr-xr-x  1 kk  staff  4 Jun 27 09:03 symlink@ -> file

답변4

이는 단순히 수십 년 동안 (과장 없이) 존재하고 작동해 온 개념인 쉘 변수를 사용하는 것입니다.

명령줄에 변수를 넣으면 쉘이 이를 대체한 다음 명령을 실행하므로 변수가 시작 부분에 있으면 분명히 명령으로 간주됩니다.

관련 정보