한 줄 명령을 사용하여 정의하고 사용하려고 합니다 alias
.bash -c
주문하다:
bash -c "eval $'df'"
잘 작동하지만:
bash -c "eval $'alias df5=df\ndf5 -h'"
아니요. alias
한 줄 명령을 통해 내부를 정의하고 사용하는 이유와 방법은 무엇입니까 ?bash -c
~에서선행은 이루기가 어렵다~의답변존재하다eval
새 줄이 포함된 명령을 한 줄에 작성하는 방법은 무엇입니까 ?:
"The is a C string"은
$'...'
" 에 전달되기 전에 리터럴 줄 바꿈으로bash
확장됩니다 .\n
eval
그러므로 내 이해는 그것이 '
에 있어야 한다는 것입니다 eval
.배쉬 매뉴얼설명하다:
문자를 작은따옴표(
'
)로 묶으면 따옴표 안의 각 문자의 리터럴 값이 유지됩니다. 앞에 백슬래시가 있더라도 작은따옴표 사이에는 작은따옴표를 사용할 수 없습니다.
내 이해는 "
가 있기 때문에 외부에서 사용해야 한다는 것입니다 eval
.'
eval
논평:
- 바라보다
eval
새 줄이 포함된 명령을 한 줄에 작성하는 방법은 무엇입니까 ?\n
대신 사용하여 설명하세요 .;
- 이 질문의 동기는 실제 명령 전체에서 다른 작업(이 명령의 모양
docker run -it ubuntu:18.04 bash -c "eval $'alias pip=pip3\nsource blah.sh; exec bash"
)에 alias 명령을 사용한다는 것입니다. 을blah.sh
사용할 위치pip
전체 실제 명령은 이지만 을 추가docker run --interactive --tty ubuntu:18.04 bash -c "apt update; apt install -y git nano wget htop python3 python3-pip unzip; git clone https://github.com/KhalilMrini/LAL-Parser; cd LAL-Parser/; alias pip=pip3; source requirements.sh; apt-get install -y libhdf5-serial-dev; alias python=python3 ; source parse.sh; exec bash"
해야 합니다 . 이 명령은 Docker 컨테이너를 시작하고 일부 요구 사항을 설치하며 일부 Python 코드를 실행합니다.eval
alias
- 이 명령은 기술적인 지식이 없는 동료를 위한 것입니다. 그들이 쉽게 사용할 수 있도록 한 줄의 명령만 실행하기를 원합니다. 그러므로 나는 명령이
Dockerfile
작동하기 위해 파일(예: 스크립트) 을 요구하는 것을 원하지 않습니다 .bash
다음 명령:
bash -c " eval 'alias df5=df df5 -h' "
그리고 명령
bash -c " alias df5=df df5 -h "
아니요. 실수
bash: line 2: df5: command not found
. 문제는alias
이유bash -c
를 모르고 해결 방법이 있는지 궁금합니다.
답변1
수정된 질문:
편집된 질문에 대해 이제 "exec bash 후에 대화형 별칭이 필요하지 않습니다":
예, bash -c는 실패합니다.
$ bash -c "
alias df5=df
df5 -h
"
bash: line 2: df5: command not found
그러나 별칭 설정이 실패했기 때문이 아닙니다.
$ bash -c "
alias df5=df
alias df5
"
alias df5=df
그러나 비대화형 셸(주로 스크립트)에서는 별칭이 기본적으로 확장되지 않으므로 다음을 수행해야 합니다.
bash -c "
alias df5=df
shopt -s expand_aliases
df5 -h
"
이것이 별칭 대신 함수를 사용하는 중요한 이유 중 하나입니다.
그것이 극복해야 할 전부라면 다음을 사용하십시오.
docker run --interactive --tty ubuntu:18.04 \
bash -c "
shopt -s expand_aliases;
apt update;
apt install -y git nano wget htop python3 python3-pip unzip;
git clone https://github.com/KhalilMrini/LAL-Parser;
cd LAL-Parser/;
alias pip=pip3;
source requirements.sh;
apt-get install -y libhdf5-serial-dev;
alias python=python3;
source parse.sh;
exec bash
"
한 줄의 코드로 작동해야 합니다(줄 바꿈이 제거됨). 그렇지 않다면 댓글을 달아주세요.
편집 전 질문:
이전 답변은 다음 문제를 해결했습니다. docker가 시작한 대화형 셸에서 끝에 exec bash
.
새로운 대화형 셸에서 별칭 사용을 방해하는 실제 문제는 전체 명령입니다.
docker run --interactive --tty ubuntu:18.04 \
bash -c "
apt update;
apt install -y git nano wget htop python3 python3-pip unzip;
git clone https://github.com/KhalilMrini/LAL-Parser;
cd LAL-Parser/;
alias pip=pip3;
source requirements.sh;
apt-get install -y libhdf5-serial-dev;
alias python=python3;
source parse.sh;
exec bash
"
로 끝납니다 exec bash
. 그러면 실행된 스크립트에 별칭도 없고 함수도 없는 새롭고 깨끗한 bash 인스턴스가 시작됩니다.
가능한 해결책 중 하나는 exec bash를 다음으로 바꾸는 것입니다.
bash --rcfile <(echo '. ~/.bashrc; alias pip=pip3; alias python=python3')
이렇게 하면 사용자(docker 명령을 실행하는 사람)가 두 개의 별칭이 정의된 대화형 셸에 배치됩니다.
참고: 이 아이디어는 많은 패키지를 설치해야 하기 때문에 테스트되지 않았지만 작동할 것입니다.
적어도 다음을 가리킨다.진짜명령에 문제가 있습니다.
답변2
를 사용하면 (다른 쉘과 달리) 별칭은 대화형 모드가 아닐 때 확장되지 않기 bash
때문에 확장되지 않습니다 .bash
이러한 bash 관련 편견 외에도 별칭 확장에 대한 더 중요한 결과가 있습니다. POSIX 표준의 다음 버전에는 별칭에 작업 권한이 부여되지 않을 때의 어려움을 설명하는 설명이 포함될 것입니다.
별칭은 파서의 어휘 분석기 부분 내에서 확장되며 별칭은 별칭이 셸에 알려져 있고 관련 텍스트 조각으로 어휘 분석기가 호출되는 경우에만 확장됩니다.뒤쪽에쉘은 이미 이 별명을 알고 있습니다.
따라서 별칭 확장을 더 잘 이해하려면 셸이 구문 분석을 수행하는 방법을 이해하는 것도 중요합니다.
쉘은 일반적으로 입력의 전체 행을 구문 분석한 후 결과를 해석하고(별명이 지정된 명령이 인식되는 경우) 다음 행을 계속 구문 분석합니다.
이는 최선의 경우 다음 코드 줄에서 별칭이 먼저 확장되는 이유를 설명합니다.
Bourne Shell
및 와 같은 전통적인 쉘의 경우 ksh
일부 경우에는 여전히 작동하지 않습니다. 그 이유는 전통적인 쉘이 결과 해석을 시작하기 전에 일부 입력을 한 줄씩 분석하는 것이 아니라 블록별로 분석하기 때문입니다. 다음 구조는 전체적으로 블록으로 구문 분석됩니다.
shell -c "cmd-arg"
크기에 관계없이 의 전체 cmd-argeval
명령 매개변수명령 대체
쉘이 시작될 때 실행되는 도트 스크립트
.
buitlin 명령을 통해 실행되는 스크립트
이 경우 명령이 서브셸에서 실행되면 정의된 별칭은 적용되지 않습니다. 다른 경우에는 구문 분석된 블록이 실행되고 다음 입력이 구문 분석된 후에 별칭이 적용됩니다.
이를 확인하려는 사람은 NLFLG
Bourne Shell 또는 ksh 소스를 확인하고 싶을 것입니다. 이 플래그가 파서에서 사용되면 개행 문자는 ;
a를 보는 것과 같은 방식으로 처리됩니다.
보시다시피 스크립트에서 별칭을 사용하지 않으면 강력한 영향을 미칠 수 있으며 현재 사용 중인 셸이 예상대로 작동하더라도 다른 셸에서는 동일한 동작이 나타나지 않습니다.