Bash 명령 행 처리

많은 형제 가 스 크 립 트 나 명령 을 쓸 때 오류 가 발생 하 는 주요 원인 은 bash 의 명령 행 처 리 를 잘 모 르 기 때 문 입 니 다.제 가 여기 서 총 결 을 했 으 니 참고 하 셔 도 됩 니 다.그 중에서 도 작은 따옴표, 작은 따옴표 와 eval 의 기교 와 관련 되 어 있 으 니 제 가 일일이 말씀 드 리 겠 습 니 다.
코드:

  
  
+-------------+ |------------------------->| |--------------------------| | ----------------------->| 1. |---- ---------------| | | | ------------------->| | | | | | | +-------------+ | | | | | || | | | | | \/ | | | | | +-------------------------------------------+ | | | | | | 2. | | | | | ------| | | | | | | | | | | | | | | | | | +-------------------------------------------+ | | | | || | | | | \/ | | | | +-----------------------------+ | | | | | 3. | | | | |------------| | | | | | | | | | +-----------------------------+ | | | || | | | \/ | | | +--------------+ | | | | 4. | | | | +--------------+ | | | || | | | \/ | | | +--------------+ | | | | 5.~ | | | | +--------------+ | | | || | | | \/ | | | +--------------+ | | | | 6. |<-----------------| | | +--------------+ | | || | | \/ | | +------------------------------+ | | | 7. ( ) | | | +------------------------------+ | | || | | \/ | | +--------------+ | | | 8. |------------------| | | +--------------+ | | | || | | | \/ | | | +--------------+ | | | | 9. | | | | +--------------+ | | | || | | | \/ | | | +--------------+ | | | | 10. | | | | +--------------+ | | | || | | | \/ | | | +----------------------------------------+ | | | | 11. : , , |<---|-----| | +----------------------------------------+ | || | \/ | +-------------+ |----------eval--------------| 12. | +-------------+

Shell 이 표준 입력 이나 스 크 립 트 에서 읽 은 줄 을 하나의 파이프 줄 이 라 고 합 니 다. 0 개 이상 의 파이프 문자 (|) 로 구 분 된 명령 을 포함 합 니 다.각 파이프 행 에 대해 12 단계 의 처 리 를 진행 하 다.
위의 삽 화 를 결합 하여 명령 행 의 12 단 계 를 드 립 니 다.
1. 명령 행 을 고정 문자 집합 으로 구 분 된 기호 로 나 눕 니 다.
SPACE, TAB, NEWLINE, ; , (, ), <, >, |, &
기호 유형 은 단어, 키워드, I / O 리 셋 문자 와 분 호 를 포함한다.
2. 각 명령 의 첫 번 째 기 호 를 검사 하고 따옴표 나 반사 선 이 없 는 키워드 인지 확인 합 니 다.if 와 다른 제어 구조의 시작 문자열, function, {또는 (, 명령 은 실제 복합 명령 입 니 다. 셸 은 내부 에서 복합 명령 을 처리 하고 다음 명령 을 읽 으 며 이 과정 을 반복 합 니 다. 키워드 가 복합 명령 의 시작 문자열 이 아니라면 (예 를 들 어 then 등 제어 구조 중간 에 나타 나 는 키워드)문법 오류 신 호 를 보 냅 니 다.
3. 별명 목록 에 따라 각 명령 의 첫 번 째 키 워드 를 검사 합 니 다. 일치 하 는 키 워드 를 찾 으 면 별명 정 의 를 바 꾸 고 첫 번 째 단 계 를 되 돌려 줍 니 다. 그렇지 않 으 면 네 번 째 단계 에 들 어 갑 니 다. 이 정책 은 별명 을 되 돌 릴 수 있 고 키워드 별명 도 정의 할 수 있 습 니 다. 예 를 들 어 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 단계 만 처리 한 다 는 것 이다.
즉, 두 따옴표 는 파이프 문자, 별명, ~ 교체, 마스크 확장, 구분자 로 단 어 를 나 누 는 것 을 무시 한 것 이다.
따옴표 에 있 는 작은 따옴표 가 작 동 하지 않 지만, 작은 따옴표 에 서 는 매개 변 수 를 바 꿀 수 있 습 니 다. 명령 바 꾸 기와 산술 표현 식 의 값 을 구 할 수 있 습 니 다. 작은 따옴표 에 작은 따옴표 가 포 함 될 수 있 습 니 다.
eval
eval 의 역할 은 명령 행 처 리 를 다시 실행 하 는 것 입 니 다. 즉, 하나의 명령 행 에 대해 두 번 의 명령 행 처 리 를 수행 하 는 것 입 니 다.
이 명령 을 잘 쓰 려 면 일정한 시간 이 필요 하 다. 나 는 두 가지 예 를 들 어 벽돌 을 던 져 옥 을 끌 어 올 렸 다.
예 1:
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]*___FCKpd___1quot; >/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 을 사용 할 필요 가 있다 고 생각 하 는 사람 이 있 을 지도 모 릅 니 다. 직접 $@ 으로 명령 을 수행 하면 되 잖 아 요.
오류! 여기 전형 적 인 예 를 보 여 드 리 겠 습 니 다.
코드:

  
  
[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' 문자열 을 다시 명령 행 으로 처리 하면 이번 에는 파 이 프 를 정확하게 분석 할 수 있 습 니 다.
한 마디 로 하면 명령 이나 스 크 립 트 디자인 이 명령 행 을 통 해 정확하게 처리 되 고 임 의 한 걸음 을 뛰 어 넘 으 면 예상 치 못 한 오 류 를 일 으 킬 수 있 습 니 다!
예 2:
시스템 의 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 프로그래머 의 필수 기술 이다.
명령 우선 순위 표
1. 별명 2. 키워드 3. 함수 4. 내장 명령 5. 스 크 립 트 또는 실행 가능 한 프로그램 ($PATH)
학습 중 에 겪 을 곤 혹 스 러 움 을 감안 하여 나 는 재 미 있 는 명령 을 내 렸 다.
command builtin enable
위의 명령 행 에서 언급 했 듯 이 11 단계 에 서 는 명령 을 찾 습 니 다. 구체 적 인 과정 은 어 떻 습 니까?
기본 검색 순 서 는 함수, 내부 명령, 스 크 립 트, 실행 가능 코드 입 니 다. 우 리 는 실제 프로 그래 밍 에서 검색 항목 을 건 너 뛰 어 일정한 기능 수 요 를 만족 시 켜 야 합 니 다. 이 세 가지 명령 으로 마법 을 사용 해 야 합 니 다 ~ ~
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 를 사용 해 야 합 니까? 함수 가 재 귀 순환 에 빠 지지 않도록 하기 위해 서 입 니 다. 함수 이름과 내 장 된 명령 이 같 기 때문에 함수 의 우선 순위 가 내 장 된 명령 보다 높 습 니 다.
builtin
말 그대로 내 장 된 명령 만 찾 습 니 다. 이 명령 은 간단 합 니 다. 더 이상 말 하지 않 겠 습 니 다.
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 는 넓 고 심오 하 니 모두 열심히 공부 하 시기 바 랍 니 다.

좋은 웹페이지 즐겨찾기