bash 명령 처리 12 단계 [zt]

많은 형제 가 스 크 립 트 나 명령 을 쓸 때 오류 가 발생 하 는 주요 원인 은 bash 의 명령 행 처 리 를 잘 모 르 기 때 문 입 니 다.제 가 여기 서 총 결 을 했 으 니 참고 하 셔 도 됩 니 다.그 중에서 도 작은 따옴표, 작은 따옴표 와 eval 의 기교 와 관련 되 어 있 으 니 제 가 일일이 말씀 드 리 겠 습 니 다.
Shell 이 표준 입력 이나 스 크 립 트 에서 읽 은 줄 을 하나의 파이프 줄 이 라 고 합 니 다. 0 개 이상 의 파이프 문자 () 로 구 분 된 명령 을 포함 합 니 다.각 파이프 행 에 대해 12 단계 의 처 리 를 진행 하 다.1. bash 명령 처리 의 12 단계; + --- --- - +작은 따옴표
-------------------------> --------------------------
기호 로 구분한다
따옴표
+-------------+
다음 명령 읽 기\/
+-------------------------------------------+
2.
첫 번 째 기호 검사
열 린 키워드 다른 키워드
비 키워드
+-------------------------------------------+
\/
+-----------------------------+
별명 확장 3. 첫 번 째 기호 검사
별명
별명 아니에요.
+-----------------------------+
\/
+--------------+
4. 대괄호 확장
+--------------+
\/
+--------------+
5. 기호 확장
+--------------+
\/
따옴표
6. 매개 변수 확장
+--------------+
\/
+------------------------------+
7. 명령 바 꾸 기 (내장 명령 행 처리)
+------------------------------+
\/
따옴표
8. 산술 확장
+--------------+
\/
+--------------+
9. 단어 분할
+--------------+
\/
+--------------+
10. 경로 이름 확장
+--------------+
\/
+----------------------------------------+
11. 명령 찾기: 함수, 내장 명령, 실행 가능 한 파일 < --- --
+----------------------------------------+
\/
다음 명령 에 파 라 메 터 를 가 져 옵 니 다.
실행 명령
+-------------+
위의 삽 화 를 결합 하여 명령 행 의 12 단 계 를 드 립 니 다.
1. 명령 행 을 고정 문자 집합 으로 구 분 된 기호 로 나 눕 니 다.SPACE, TAB, NEWLINE, ; , (, ), <, >, , &
기호 유형 은 단어, 키워드, I/O 리 셋 문자 와 분 호 를 포함한다.
2. 각 명령 의 첫 번 째 기 호 를 검사 하고 따옴표 나 반사 선 이 없 는 키워드 인지 확인 합 니 다.
if 와 다른 제어 구조의 시작 문자열, function, {또는 (, 명령 은 실제 복합 명령 입 니 다. 셸 은 내부 에서 복합 명령 을 처리 하고 다음 명령 을 읽 으 며 이 과정 을 반복 합 니 다. 키워드 가 복합 명령 의 시작 문자열 이 아니라면 (예 를 들 어 then 등 제어 구조 중간 에 나타 나 는 키워드)문법 오류 신 호 를 보 냅 니 다.
3. 별명 목록 에 따라 각 명령 의 첫 번 째 키 워드 를 검사 합 니 다.
일치 하 는 것 을 찾 으 면 별명 정 의 를 바 꾸 고 첫 번 째 단 계 를 되 돌려 줍 니 다. 그렇지 않 으 면 4 단계 에 들 어 갑 니 다. 이 정책 은 별명 을 재 귀적 으로 사용 할 수 있 고 키워드 별명 도 정의 할 수 있 습 니 다. 예 를 들 어 alias procedure = function.
4. 대괄호 확장 을 실행 합 니 다. 예 를 들 어 a {b, c} 이 ab ac 로 변 합 니 다.
5 、 단어 첫머리 에 있 으 면 $HOME 로 교체 ~.
usr 의 홈 디 렉 터 리 를 사용 하여 ~ user 를 교체 합 니 다.
6. 기호 $로 시작 하 는 표현 식 에 대해 매개 변수 (변수) 를 교체 합 니 다.
7. 형식 $(string) 의 표현 식 을 명령 으로 교체 합 니 다.
이것 은 포 함 된 명령 행 처리 입 니 다.
8. 계산 형식 이 $(string) 인 산술 표현 식;
9. 줄 의 인자, 명령 과 산술 교체 부분 을 다시 단어 로 나 눕 니 다. 이번 에는 1 단계 의 메타 문자 집합 이 아 닌 $IFS 의 문 자 를 분할 문자 로 사용 합 니 다.
10. 출현 *,?, [/] 실행 경로 이름 확장 을 어댑터 확장 이 라 고도 합 니 다.
11. 명령 우선 순위 표 (별명 건 너 뛰 기) 에 따라 명령 을 찾 습 니 다.
12. I/O 재 설정 과 다른 작업 을 한 후에 이 명령 을 수행 합 니 다.
인용
1. 작은 따옴표 가 앞의 10 단 계 를 뛰 어 넘 었 기 때문에 작은 따옴표 에 작은 따옴표 2, 작은 따옴표 가 1 ~ 5, 9 ~ 10 단 계 를 뛰 어 넘 으 면 안 됩 니 다. 즉, 6 ~ 8 단계 만 처리 하 는 것 입 니 다.
즉, 두 따옴표 는 파이프 문자, 별명, ~ 교체, 마스크 확장 과 구분자 로 단 어 를 나 누 는 것 을 무시 한 것 입 니 다. 두 따옴표 에 있 는 작은 따옴표 는 작용 하지 않 지만, 두 따옴표 에 서 는 매개 변 수 를 바 꿀 수 있 습 니 다. 명령 교체 와 산술 표현 식 의 값 을 구 할 수 있 습 니 다. 두 따옴표 에 두 따옴표 가 포함 되 어 있 습 니 다. 방식 은 전의 부 호 를 추가 하 는 것 입 니 다.
3. eval 의 역할;
eval 의 역할 은 명령 행 처 리 를 다시 집행 하 는 것 입 니 다. 즉, 하나의 명령 행 에 대해 두 번 의 명령 행 처 리 를 하 는 것 입 니 다. 이 명령 을 잘 사용 하려 면 어느 정도 시간 이 걸 립 니 다. 저 는 두 가지 예 를 들 어 벽돌 을 던 져 옥 을 끌 어 올 립 니 다.
1. 예 1: eval 기법 으로 셸 의 제어 구 조 를 실현 합 니 다 for
eval 기법 으로 셸 의 제어 구 조 를 실현 합 니 다 for.[root@home root]# cat myscript1
#!/bin/sh
evalit(){
         if [ $cnt = 1 ];then
                 eval $@
                 return
         else
                 let cnt=cnt-1
                 evalit $@
         fi
         eval $@
}
cnt=$1
echo $cnt egrep "^[1-9][0-9]*$" >/dev/null
if [ $? -eq 0 ]; then
         shift
         evalit $@
else
         echo 'ERROR!!! Check your input!'
fi
[root@home root]# ./myscript1 3 hostname
home
home
home
[root@home root]# ./myscript1 5 id cut -f1 -d' '
uid=0(root)
uid=0(root)
uid=0(root)
uid=0(root)
uid=0(root)

메모: bash 에는 두 개의 특수 한 변수 가 있 습 니 다. 매개 변수 목록 을 저장 합 니 다.
$*, $IFS 가 지정 한 분할 문자 로 분 할 된 문자열 그룹 을 저 장 했 습 니 다. $@, 매개 변수 목록, 즉 "$1", "$2"를 그대로 저 장 했 습 니 다.
함수 재 귀 및 eval 을 사용 하여 for 구 조 를 실 현 했 습 니 다. eval $@ 을 실 행 했 을 때 다음 과 같은 절 차 를 거 쳤 습 니 다. 첫 번 째 단 계 는 eval $@ 6 단계 로 나 누 어 $@ 을 hostname 11 단계 로 확장 하고 내 장 된 명령 eval 을 찾 아 명령 행 처 리 를 반복 합 니 다. 11 단계, hostname 명령 을 찾 아 실행 합 니 다.
메모: 당연히 eval 을 사용 할 필요 가 있다 고 생각 하 는 사람 이 있 을 지도 모 릅 니 다. 직접 $@ 으로 명령 을 수행 하면 되 잖 아 요.
예 2: 전형 적 인 잘못된 예
오류! 여기 전형 적 인 예 를 보 여 드 리 겠 습 니 다.[root@home root]# a="id cut -f1 -d' '"
[root@home root]# $a
id: -- f
‘id --help’ 。
[root@home root]# eval $a
uid=0(root)

명령 행 이 복잡 하면 (파이프 나 다른 문자 포함) $a 문자열 을 직접 실행 하 는 데 오류 가 발생 합 니 다. 분석 은 다음 과 같 습 니 다.
$a 의 처 리 는 6 단계 에 있 습 니 다. 매개 변수 확장, 즉 파이프 분석 을 건 너 뛰 었 습 니 다. 그래서 ","cut ","- f1 ","- d "는 모두 id 명령 의 매개 변수 가 되 었 습 니 다. 물론 오류 가 발생 했 습 니 다.
그러나 eval 을 사 용 했 습 니 다. 첫 번 째 명령 행 에서 얻 은 'id', 'cut', '- f1', '- d' 문자열 을 다시 명령 행 으로 처리 하면 이번 에는 파 이 프 를 정확하게 분석 할 수 있 습 니 다.
한 마디 로 하면 명령 이나 스 크 립 트 디자인 이 명령 행 을 통 해 정확하게 처리 되 고 임 의 한 걸음 을 뛰 어 넘 으 면 예상 치 못 한 오 류 를 일 으 킬 수 있 습 니 다!
예 3: 시스템 의 ls 색상 표시 설정eval $(dircolors -b /etc/dircolors)
eval 문 구 는 셸 에 게 eval 인 자 를 받 아들 이 고 명령 행 으로 처리 하 는 모든 절 차 를 통 해 실 행 됩 니 다.
스 크 립 트 를 만들어 서 명령 문자열 을 마음대로 만 들 고 셸 에 전달 할 수 있 습 니 다.
$() 는 명령 을 바 꾸 고 명령 을 되 돌려 주 는 출력 문자열 입 니 다.
그 중에서 dircolors 명령 은/etc/dircolors 설정 파일 에 따라 환경 변 수 를 설정 하 는 LS COLORS 의 bash 코드 를 생 성 합 니 다. 내용 은 다음 과 같 습 니 다.[root@localhost root]# dircolors -b > tmp
[root@localhost root]# cat tmp
LS_COLORS='no=00:fi=00:di=01;34:ln=01; ......
eXPort LS_COLORS
# , dircolors 。
eval shell 。

eval 은 Bash Shell 명령 행 처리 규칙 에 대한 유연 한 응용 으로 '스마트' 명령 을 구성 하여 복잡 한 기능 을 실현 한다.
위 에서 언급 한 명령 은 eval 의 일반적인 응용 프로그램 으로 명령 행 매개 변수 전달 과정 을 1 회 반복 하여 명령 을 순수 하 게 수행 하 는 명령 입 니 다.
사실 이것 은 bash 의 난점 이 고 고급 bash 프로그래머 의 필수 기술 이다.
4. 명령 우선 순위 표 1, 별명 2, 키워드 3, 함수 4, 내장 명령 5, 스 크 립 트 또는 실행 가능 한 프로그램 ($PATH) 5. 학습 중 에 겪 을 곤 혹 스 러 움 을 감안 하여 재 미 있 는 명령 을 드 리 겠 습 니 다.
1、command builtin enable
위의 명령 행 에서 언급 했 듯 이 11 단 계 는 명령 을 찾 습 니 다. 구체 적 인 과정 은 어 떻 습 니까? 기본 검색 순 서 는 함수, 내부 명령, 스 크 립 트, 실행 가능 코드 입 니 다. 우 리 는 실제 프로 그래 밍 에서 검색 항목 을 건 너 뛰 어 일정한 기능 수 요 를 만족 시 켜 야 합 니 다. 이 세 가지 명령 을 사용 하여 마법 을 사용 해 야 합 니 다 ~
2、command
별명 과 함수 찾기 를 건 너 뛰 었 습 니 다. 다시 말 하면 내부 명령 과 검색 경로 에서 찾 은 스 크 립 트 나 실행 가능 한 프로그램 만 찾 습 니 다. 재 미 있 는 예 를 들 어 보 겠 습 니 다.[root@home root]# type -all pwd
pwd is a shell builtin
pwd is /bin/pwd
[root@home root]# cat myscript2
#!/bin/sh
pwd(){
         echo "This is the current Directory."
         command pwd
}
pwd
[root@home root]# ./myscript2
This is the current directory.
/root

내 장 된 명령 pwd 와 외부 명령/bin/pwd 를 pwd () 함수 로 대체 한 다음 스 크 립 트 에서 내 장 된 명령 pwd 를 실행 합 니 다. 여기 서 우 리 는 왜 command 를 사용 해 야 합 니까? 함수 가 재 귀 순환 에 빠 지지 않도록 하기 위해 서 입 니 다. 함수 이름과 내 장 된 명령 이 같 기 때문에 함수 의 우선 순위 가 내 장 된 명령 보다 높 습 니 다.
3、builtin
말 그대로 내 장 된 명령 만 찾 습 니 다. 이 명령 은 간단 합 니 다. 더 이상 말 하지 않 겠 습 니 다.
4、enable
builtin 과 달리 내 장 된 명령 을 차단 합 니 다. 셸 스 크 립 트 나 같은 이름 의 실행 가능 코드 를 실행 할 수 있 도록 해 줍 니 다. 예 를 들 어 보 세 요.
pwd 명령 은 두 가지 가 있 습 니 다. 하 나 는 셸 내 장 된 것 이 고 하 나 는 실행 가능 한 프로그램 입 니 다.
이상 한 경로 이름 을 실행 하면 셸 에 내 장 된 pwd 는 '오류 정보' 를 출력 하지만 외부 pwd 는 현재 디 렉 터 리 의 '원래 모습' 을 출력 합 니 다. 아래 를 보십시오.[root@home root]# cd //
[root@home //]# pwd
//
[root@home //]# type -all pwd
pwd is a shell builtin
pwd is /bin/pwd
[root@home //]# /bin/pwd
/
[root@home //]# enable -n pwd
[root@home //]# pwd
/

이렇게 하면 enable - n 으로 내 장 된 pwd 명령 을 차단 한 후 외부 pwd 로 정확 한 경로 이름 을 출력 할 수 있 습 니 다.
Bash 는 넓 고 심오 하 니 모두 열심히 공부 하 시기 바 랍 니 다.:)

좋은 웹페이지 즐겨찾기