http://kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/index.html

 

Shell 스크립트에 대한 좋은 정보가 있다!!!!

 

야 멋진다!!

 

 

고급 Bash 스크립팅 가이확인

Bash를 이용한 쉘 스크립팅 완전 가이드

Mendel Cooper

Brindlesoft

thegrendel (at) theriver.com

차현진

terminus (at) kldp.org

2001년 12월 16일

본 튜토리얼은 여러분이 Bash에 대해서 어떠한 사전 지식도 없다고 가정을 합니다만, 금방 중/고급 수준의 명령어들을 소개합니다(...유닉스의 슬기롭고 교훈적인 부분들을 배워 나가면서). 이 문서는 교과서나, 혼자 공부할 때 볼 수 있는 메뉴얼, 쉘 스크립팅 기술에 대한 레퍼런스및 소스로 쓰일 수 있습니다. 스크립트를 배우는 유일한 방법은 스크립트를 직접 짜 보는 것이다라는 전제하에, 연습문제와 아주 자세하게 주석 처리된 예제들로 능동적인 독자들의 참여를 유도할 것입니다.

이 문서의 최신 버전은 저자의 홈페이지에서 SGML 소스와 HTML을 "타르볼"형태로 얻을 수 있습니다. 고침 변경 사항은 change log를 참고하세요.

고친 과정
고침 0.1 2000년 6월 14일 고친이 mc
초기 릴리스.
고침 0.2 2000년 10월 30일 고친이 mc
버그 수정, 내용및 예제 스크립트 추가.
고침 0.3 2001년 2월 12일 고친이 mc
메이저 업데이트.
고침 0.4 2001년 7월 8일 고친이 mc
버그 수정, 더 많은 내용및 예제 추가 - 완전한 책 형태의 개정판.
고침 0.5 2001년 9월 3일 고친이 mc
메이저 업데이트. 버그 수정, 내용 추가, 장과 절을 재편성.
고침 1.0.11 2001년 12월 16일 고친이 mc
버그 수정, 재편성, 내용 추가. Stable release.

바치는 글

모든 마법의 근원인 Anita에게 이 책을 바칩니다.

차례
Part 1. 소개
1. 왜 쉘 프로그래밍을 해야 하죠?
2. #! 으로 시작하기
2.1. 스크립트 실행하기
2.2. 몸풀기 연습문제(Preliminary Exercises)
Part 2. 기초 단계
3. 종료와 종료 상태(Exit and Exit Status)
4. 특수 문자
5. 변수와 매개변수 소개
5.1. 변수 치환(Variable Substitution)
5.2. 변수 할당(Variable Assignment)
5.3. Bash 변수는 타입이 없다(untyped)
5.4. 특수한 변수 타입
6. 쿼우팅(quoting)
7. 테스트
7.1. 테스트(Test Constructs)
7.2. 파일 테스트 연산자
7.3. 비교 연산자(이진)
7.4. 중첩된 if/then 조건 테스트
7.5. 여러분이 테스트문을 얼마나 이해했는지 테스트 해보기
8. 연산자 이야기(Operations and Related Topics)
8.1. 연산자(Operators)
8.2. 숫자 상수(Numerical Constants)
Part 3. 중급 단계(Beyond the Basics)
9. 변수 재검토(Variables Revisited)
9.1. 내부 변수(Internal Variables)
9.2. 문자열 조작
9.3. 매개변수 치환(Parameter Substitution)
9.4. 변수 타입 지정: declaretypeset
9.5. 변수 간접 참조
9.6. $RANDOM: 랜덤한 정수 만들기
9.7. 이중소괄호(The Double Parentheses Construct)
10. 루프와 분기(Loops and Branches)
10.1. 루프
10.2. 중첩된 루프
10.3. 루프 제어
10.4. 테스트와 분기(Testing and Branching)
11. 내부 명령어(Internal Commands and Builtins)
11.1. 작업 제어 명령어
12. 외부 필터, 프로그램, 명령어
12.1. 기본 명령어
12.2. 복잡한 명령어
12.3. 시간/날짜 명령어
12.4. 텍스트 처리 명령어
12.5. 파일, 아카이브(archive) 명령어
12.6. 통신 명령어
12.7. 터미널 제어 명령어
12.8. 수학용 명령어
12.9. 기타 명령어
13. 시스템과 관리자용 명령어
14. 명령어 치환(Command Substitution)
15. 산술 확장(Arithmetic Expansion)
16. I/O 재지향
16.1. exec 쓰기
16.2. 코드 블럭 재지향
16.3. 응용
17. Here Documents
18. 쉬어가기
Part 4. 고급 주제들(Advanced Topics)
19. 정규 표현식(Regular Expressions)
19.1. 정규 표현식의 간략한 소개
19.2. Globbing
20. 서브쉘(Subshells)
21. 제한된 쉘(Restricted Shells)
22. 프로세스 치환(Process Substitution)
23. 함수
23.1. 복잡 함수와 함수의 복잡성(Complex Functions and Function Complexities)
23.2. 지역 변수와 재귀 함수(Local Variables and Recursion)
24. 별칭(Aliases)
25. 리스트(List Constructs)
26. 배열
27. 파일들
28. /dev 와 /proc
28.1. /dev
28.2. /proc
29. 제로와 널(Of Zeros and Nulls)
30. 디버깅
31. 옵션
32. 몇 가지 지저분한 것들(Gotchas)
33. 스타일 있게 스크립트 짜기
33.1. 비공식 쉘 스크립팅 스타일시트
34. 자질구레한 것들
34.1. 대화(interactive)형 모드와 비대화(non-interactive)형 모드 쉘과 스크립트
34.2. 쉘 래퍼(Shell Wrappers)
34.3. 테스트와 비교: 다른 방법
34.4. 최적화
34.5. 팁 모음(Assorted Tips)
34.6. 괴상한 것(Oddities)
34.7. 이식성 문제(Portability Issues)
34.8. 윈도우즈에서의 쉘 스크립팅
35. Bash, 버전 2
36. 후기(Endnotes)
36.1. 저자 후기(Author's Note)
36.2. 저자에 대해서
36.3. 이 책을 만드는데 쓴 도구들
36.3.1. 하드웨어
36.3.2. 소프트웨어와 프린트웨어
36.4. 크레딧
서지사항
A. 여러분들이 보내준 스크립트들(Contributed Scripts)
B. Sed 와 Awk 에 대한 간단한 입문서
B.1. Sed
B.2. Awk
C. 특별한 의미를 갖는 종료 코드
D. I/O와 I/O 재지향에 대한 자세한 소개
E. 지역화(Localization)
F. 샘플 .bashrc 파일
G. 도스(DOS) 배치 파일을 쉘 스크립트로 변환
H. 연습문제
I. Copyright
예 목록
2-1. cleanup: /var/log 에 있는 로그 파일들을 청소하는 스크립트
2-2. cleanup: 위 스크립트의 향상되고 일반화된 버전.
3-1. 종료/종료 상태
3-2. !으로 조건을 부정하기
4-1. 코드 블럭과 I/O 재지향
4-2. 코드 블럭의 결과를 파일로 저장하기
4-3. 최근 하루동안 변경된 파일들을 백업하기
5-1. 변수 할당과 치환
5-2. 평범한 변수 할당
5-3. 평범하고 재미있는 변수 할당
5-4. 정수? 문자열?
5-5. 위치 매개변수
5-6. wh, whois 도메인 네임 룩업
5-7. shift 쓰기
6-1. 이상한 변수를 에코하기
6-2. 이스케이프된 문자들
7-1. 무엇이 참인가?
7-2. [ ]test 의 동일함
7-3. (( ))로 산술식 테스트 하기
7-4. 산술 비교와 문자열 비교
7-5. 문자열이 인지 테스트 하기
7-6. zmost
8-1. 산술 연산자 쓰기
8-2. && 와 || 를 쓴 복합 조건 테스트
8-3. 숫자 상수 표기법:
9-1. $IFS 와 빈 칸
9-2. 타임 아웃 처리 입력
9-3. 타임 아웃 처리 입력, 한 번 더
9-4. 내가 루트인가?
9-5. arglist: $* 과 $@ 로 인자를 나열하기
9-6. 일관성 없는 $*$@의 동작
9-7. $IFS 가 비어 있을 때 $*$@
9-8. 밑줄 변수(underscore variable)
9-9. 그래픽 파일을 다른 포맷 확장자로 이름을 바꾸면서 변환
9-10. 매개변수 치환과 : 쓰기
9-11. 변수의 길이
9-12. 매개변수 치환에서의 패턴 매칭
9-13. 파일 확장자 바꾸기:
9-14. 임의의 문자열을 파싱하기 위해 패턴 매칭 사용하기
9-15. 문자열의 접두, 접미어에서 일치하는 패턴 찾기
9-16. declare를 써서 변수 타입 지정하기
9-17. 간접 참조
9-18. awk에게 간접 참조를 넘기기
9-19. 랜덤한 숫자 만들기
9-20. RANDOM 으로 주사위를 던지기
9-21. RANDOM 에 seed를 다시 지정해 주기
9-22. C 형태의 변수 조작
10-1. 간단한 for 루프
10-2. 각 [list] 항목이 인자를 두 개씩 갖는 for
10-3. Fileinfo: 변수에 들어 있는 파일 목록에 대해 동작
10-4. for 문에서 파일 조작하기
10-5. in [list]가 빠진 for
10-6. for 문의 [list]에 명령어 치환 쓰기
10-7. 이진 파일에 grep 걸기
10-8. 특정 디렉토리의 모든 바이너리 파일에 대해 원저작자(authorship)를 확인 하기
10-9. 디렉토리에 들어 있는 심볼릭 링크들을 나열하기
10-10. 디렉토리에 들어 있는 심볼릭 링크들을 파일로 저장하기
10-11. C 형태의 for 루프
10-12. 배치 모드로 efax 사용하기
10-13. 간단한 while 루프
10-14. 다른 while 루프
10-15. 다중 조건 while 루프
10-16. C 형태의 문법을 쓰는 while 루프
10-17. until 루프
10-18. 중첩된 루프
10-19. 루프에서 breakcontinue의 영향
10-20. 여러 단계의 루프에서 탈출하기
10-21. 더 상위 루프 레벨에서 계속하기(continue)
10-22. case 쓰기
10-23. case로 메뉴 만들기
10-24. case용 변수를 만들기 위해서 명령어 치환 쓰기
10-25. 간단한 문자열 매칭
10-26. 입력이 알파벳인지 확인하기
10-27. select로 메뉴 만들기
10-28. 함수에서 select를 써서 메뉴 만들기
11-1. printf가 실제로 쓰이는 예제
11-2. read로 변수 할당하기
11-3. read로 여러줄의 입력 넣기
11-4. read파일 재지향과 같이 쓰기
11-5. 현재 작업 디렉토리 변경하기
11-6. let으로 몇 가지 산술 연산을 하기.
11-7. eval의 효과 보여주기
11-8. 강제로 로그 아웃 시키기
11-9. "rot13" 버전
11-10. 위치 매개변수와 set 쓰기
11-11. 변수를 "언셋"(unset) 하기
11-12. export를 써서, 내장된 awk 스크립트에 변수를 전달하기
11-13. getopts로 스크립트로 넘어온 옵션과 인자 읽기
11-14. 데이타 파일 "포함하기"
11-15. exec 효과
11-16. 작업을 계속 해 나가기 전에 프로세스가 끝나길 기다리기
12-1. CDR 디스크를 구울 때 ls로 목차 만들기
12-2. Badname, 파일 이름에 일반적이지 않은 문자나 공백 문자를 포함하는 파일을 지우기.
12-3. inode 로 파일을 지우기
12-4. 시스템 로그 모니터링용 xargs 로그 파일
12-5. copydir. xargs로 현재 디렉토리를 다른 곳으로 복사하기
12-6. expr 쓰기
12-7. date 쓰기
12-8. 스크립트에서 두 파일을 비교하기 위해 cmp 쓰기.
12-9. 낱말 빈도수 분석
12-10. 10자리 랜덤한 숫자 만들기
12-11. tail로 시스템 로그를 모니터하기
12-12. 스크립트에서 "grep"을 에뮬레이트 하기
12-13. 목록에 들어 있는 낱말들의 유효성 확인하기
12-14. toupper: 파일 내용을 모두 대문자로 바꿈.
12-15. lowercase: 현재 디렉토리의 모든 파일명을 소문자로 바꿈.
12-16. du: 도스용 텍스트 파일을 UNIX용으로 변환.
12-17. rot13: 초허접(ultra-weak) 암호화, rot13.
12-18. "Crypto-Quote" 퍼즐 만들기
12-19. 파일 목록 형식화.
12-20. column 으로 디렉토리 목록을 형식화 하기
12-21. nl: 자기 자신에게 번호를 붙이는 스크립트.
12-22. cpio로 디렉토리 트리 옮기기
12-23. rpm 아카이브 풀기
12-24. C 소스에서 주석을 제거하기
12-25. /usr/X11R6/bin 둘러보기
12-26. basenamedirname
12-27. 인코드된 파일을 uudecode하기
12-28. 저당에 대한 월 상환액(Monthly Payment on a Mortgage)
12-29. 진법 변환(Base Conversion)
12-30. 다른 방법으로 bc 실행
12-31. seq로 루프에 인자를 만들어 넣기
12-32. 키보드 입력을 갈무리하기
12-33. 파일을 안전하게 지우기
12-34. m4 쓰기
13-1. 지움 글자(erase character) 세팅하기
13-2. 비밀스런 비밀번호: 터미널 에코 끄기
13-3. 키누름 알아내기
13-4. pidof 로 프로세스를 죽이기
13-5. CD 이미지 확인하기
13-6. 한 파일에서 한번에 파일 시스템 만들기
13-7. 새 하드 드라이브 추가하기
13-8. killall, /etc/rc .d/init.d 에서 인용
16-1. exec으로 표준입력을 재지향 하기
16-2. 재지향된 while 루프
16-3. 다른 형태의 재지향된 while 루프
16-4. 재지향된 until 루프
16-5. 재지향된 for 루프
16-6. 재지향된 for 루프(표준입력, 표준출력 모두 재지향됨)
16-7. 재지향된 if/then 테스트
16-8. 이벤트 로깅하기
17-1. dummyfile: 두 줄짜리 더미 파일 만들기
17-2. broadcast: 로그인 해 있는 모든 사람들에게 메세지 보내기
17-3. cat으로 여러 줄의 메세지 만들기
17-4. 탭이 지워진 여러 줄의 메세지
17-5. Here document에서 매개변수 치환하기
17-6. 매개변수 치환 끄기
17-7. upload: "Sunsite" incoming 디렉토리에 파일 한 쌍을 업로드
17-8. "아무개"(anonymous) Here Document
20-1. 서브쉘에서 변수의 통용 범위(variable scope)
20-2. 사용자 프로파일 보기
20-3. 프로세스를 서브쉘에서 병렬로 돌리기
21-1. 제한된 모드로 스크립트 돌리기
23-1. 간단한 함수
23-2. 매개변수를 받는 함수
23-3. 두 숫자중 큰 수 찾기
23-4. 숫자를 로마 숫자로 바꾸기
23-5. 함수에서 큰 값을 리턴하는지 테스트하기
23-6. 큰 두 정수 비교하기
23-7. 사용자 계정 이름에서 실제 이름을 알아내기
23-8. 지역 변수의 영역(Local variable visibility)
23-9. 지역 변수를 쓴 재귀 함수
24-1. 스크립트에서 쓰이는 별칭(alias)
24-2. unalias: 별칭을 설정, 해제하기
25-1. "and list"를 써서 명령어줄 인자 확인하기
25-2. "and list"를 써서 명령어줄 인자를 확인하는 다른 방법
25-3. "or lists""and list"를 같이 쓰기
26-1. 간단한 배열 사용법
26-2. 배열의 특별한 특성 몇 가지
26-3. 빈 배열과 빈 원소
26-4. 아주 오래된 친구: 버블 정렬(Bubble Sort)
26-5. 복잡한 배열 어플리케이션: 에라토스테네스의 체(Sieve of Erastosthenes)
26-6. 복잡한 배열 어플리케이션: 기묘한 수학 급수 탐색(Exploring a weird mathematical series)
26-7. 2차원 배열을 흉내낸 다음, 기울이기(tilting it)
28-1. 특정 PID와 관련있는 프로세스 찾기
28-2. 온라인 연결 상태
29-1. 쿠키 항아리를 숨기기
29-2. /dev/zero로 스왑 파일 세팅하기
29-3. 램디스크 만들기
30-1. 버그 있는 스크립트
30-2. test24, 버그가 있는 다른 스크립트
30-3. "assert"로 조건을 테스트하기
30-4. exit 잡아채기(Trapping at exit)
30-5. Control-C 가 눌렸을 때 깨끗이 청소하기
30-6. 변수 추적하기
32-1. 서브쉘 함정(Subshell Pitfalls)
34-1. 쉘 래퍼(shell wrapper)
34-2. 조금 복잡한 쉘 래퍼(shell wapper)
34-3. awk 스크립트 쉘 래퍼(shell wrapper)
34-4. Bash 스크립트에 내장된 펄
34-5. 하나로 묶인 Bash 스크립트와 펄 스크립트
34-6. 자신을 재귀적으로 부르는 스크립트
35-1. 문자열 확장
35-2. 간접 변수 참조 - 새로운 방법
35-3. 배열과 약간의 트릭을 써서 한 벌의 카드를 4명에게 랜덤하게 돌리기
A-1. manview: 포맷된 맨 페이지를 보는 스크립트
A-2. mailformat: 이메일 메세지를 포맷해서 보기
A-3. rn: 간단한 파일이름 변경 유틸리티
A-4. encryptedpw: 로컬에 암호화 되어 있는 비밀번호로 ftp 사이트에 파일을 업로드하는 스크립트
A-5. copy-cd: 데이타 CD를 복사하는 스크립트
A-6. days-between: 두 날짜 사이의 차이를 계산해 주는 스크립트
A-7. behead: 메일과 뉴스 메세지 헤더를 제거해 주는 스크립트
A-8. ftpget: ftp에서 파일을 다운로드 해 주는 스크립트
A-9. password: 8 글자짜리 랜덤한 비밀번호 생성 스크립트
A-10. fifo: 네임드 파이프를 써서 매일 백업해 주는 스크립트
A-11. 나머지 연산자로 소수 생성하기
A-12. tree: 디렉토리 구조를 트리 형태로 보여주는 스크립트
A-13. 문자열 함수들: C 형태의 문자열 함수
A-14. 객체 지향 데이타 베이스
F-1. 샘플 .bashrc 파일
G-1. VIEWDATA.BAT: 도스용 배치 파일
G-2. viewdata.sh: VIEWDATA.BAT 의 스크립트 버전

Posted by '김용환'
,

과거엔.. 이렇게..

 

#!/bin/bash

 EXT_CLASSPATH=''
etcjarfiles=(`find /usr/j2se/jre/lib/ext -name "*.jar" -print  `)
for etcjarfile in ${etcjarfiles[@]}; do
        EXT_CLASSPATH=${EXT_CLASSPATH}:${etcjarfile}
done

#echo $EXT_CLASSPATH

 

 

지금은 이렇게. shell script의 string 관련 스크립트를 이용하여 깔끔하게 해결~

 

 

#!/bin/bash

PATH1='/usr/j2se/jre/lib/ext'

for file in $PATH1/*
do
   filename=${file}
    echo "${filename##/*/}"
done

 

'unix and linux' 카테고리의 다른 글

bash 문자열 조작  (0) 2008.06.20
고급 Bash 스크립팅 가이드  (0) 2008.06.20
CentOS, Red hat Enterprise Edition 단상  (0) 2008.06.05
서비스 장애  (0) 2008.05.03
option parsing - bash, perl, c  (0) 2008.04.15
Posted by '김용환'
,

이 글은 지극히 개인적인 글이다...

 

CentOS는 기존에 쓰고 있었던 Red hat Enterprise Linux (이하 RHEL)에서 오픈된 소스를 기반으로 제작된 clone 판입니다. 기능상 아무런 차이가 없습니다.

레드햇에서 제공하는 업데이트 관리 기능의 서비스만을 제공받지 못할 뿐입니다.(온라인 업데이트가 up2date가 아니라 yum으로 됨)

www.centos.org에서 지원을 기대할 수 있습니다.

 

RHEL은 기술지원을 모토로 만들어진 것이고요. 사용자에 따른 customizing을 지원하지 않고, 모든 업데이트를 redhat 본사로부터 기존과 호환성을 최대한 지켜주는 bug fix security fix를 지원을 받습니다.

하지만, 이는 업데이트 시간이 오랫동안 소요되게 하고, 저희가 비싸게 비용을 지불하였습니다. 또한 기술지원은 미국 내부가 아니면 많이 미흡하다고 합니다.

 

18개월 주기로 major 버젼이 발표되고, Release된 버젼은 7년까지 업데이트를 제공한다고 합니다.

 

 

'unix and linux' 카테고리의 다른 글

고급 Bash 스크립팅 가이드  (0) 2008.06.20
특정 디렉토리에서 파일명 뽑아내기  (0) 2008.06.20
서비스 장애  (0) 2008.05.03
option parsing - bash, perl, c  (0) 2008.04.15
rsync FAQ  (0) 2008.04.10
Posted by '김용환'
,

서비스 장애

unix and linux 2008. 5. 3. 05:09

 

top 명령어 이용

top - 19:35:53 up 162 days, 17:45,  2 users,  load average: 0.00, 0.00, 0.00
Tasks:  85 total,   1 running,  84 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0% us,  0.1% sy,  0.0% ni, 99.8% id,  0.1% wa,  0.0% hi,  0.0% si
Mem:   2074864k total,   998028k used,  1076836k free,    67252k buffers
Swap:  2096472k total,        0k used,  2096472k free,   543748k cached

보통 load average 의 수치중 cpu당 2가 넘으면 서비스 지연 현상이라고 판단한다.

 

예를 들어 dual core 1 짜리는 4가 넘으면 서비스 장애라 판단하고, 즉각적인 조치를 취해야 한다.

 

 

아파치 프로세스 갯수 이용

pstree | grep httpd

일반 웹서버는 보통 200 밑을 유지하도록 하는 게 좋다.  (사실 정확하게 말하면 이건 거짓이다. 서비스마다 많이 불려지는 URL에 따라서 성능은 좌우된다... 우리회사의 경우는 200밑을 유지시키고, transaction(server-status)이 30밑이 안넘게 한다.)

절대 이 수치는 상대적인 값이다. 중형서버의 경우, 쿼드 쿼어의 경우가 각각 다르다.

 

하지만, 경험상 수치가 비정상적으로 급격하게 올라가는 경우.. 이는 어딘가 바틀렉이 생기거나 아파치 리쿼스트가 엄청나게 들어오는 경우를 의미한다.

 

io stat 확인

dmesg 이용하여 파일쪽에 이상이 없는 지 확인한다

또한 네트웍 연결하다가 소켓 타임아웃이 나면서 리쿼스트가 많이 쌓여서 바틀렉이 있는지 확인한다.

 

Sar 명령어 이용하여 cpu, network, io쪽을 잘 보면서 서비스 장애 원인을 시스템적으로 파고,

apache, tomcat 로그도 보면서 정확하게 원인분석이 필요하다.

 

 

 

Posted by '김용환'
,

bash와 perl, c언어에서의 파라미터 옵션 파싱 코드를 잘 정리한 문서가 있어서 소개한다.
실제로 이렇게 사용하고 있으므로 알고 있는 것이 좋다.


http://systhread.net/texts/200704optparse.php

Options Parsing

Options parsing can be difficult at times to say the least. There exist a number of common methods and libraries to assist with options parsing. In this text, a look at writing option and argument parsing homespun and with a little help.

Simple Parsing in sh

Simple parsing is easy in the shell:

while [ "$#" -gt "0" ]
do
case $1 in
-F)
F_FLAG=1
;;
-f)
shift
FILE_ARGUMENET=$1
;;
-u)
Usage
exit 0
;;
*)
echo "Syntax Error"
Usage
exit 1
;;
esac
shift
done

Above, the input string is iterated over and particular options act or assign a variable. The posix getopt capability allows for built in - parsing:

while getopts ":f:Fu" opt; do
case $opt in
F) F_FLAG=1;;
f) FILE_ARGUMENT=$OPTARG;;
u) usage;;
*) usage
exit 1
;;
esac
shift
done

A colon after an option indicates it requires an argument. The getopt code is far more compact than the first example. What if the script requires long options? One approach is simply to hard code long options:

while [ "$#" -gt "0" ]
do
case $1 in
-F|--setflag)
F_FLAG=1
;;
-f|--file)
shift
FILE_ARGUMENET=$1
;;
-u|--usage)
Usage
exit 0
;;
*)
echo "Syntax Error"
Usage
exit 1
;;
esac
shift
done

Setting up long options appears to be simple, however, it can quickly get out of control using the method show above. Instead, writing code to handle long options that can either be sourced in or easily dropped into scripts makes far more sense. Grigoriy Strokin has a good script that can either be copied in or sourced and can be found on his website. Following is the same code from above using getoptex:

. getoptx.sh
while getoptex "F; f; u. setflag file usage." "$@"; do
F) F_FLAG=1;;
f) FILE_ARGUMENT=$OPTARG;;
u) usage;;
*) usage
exit 1
;;
done

It is pretty obvious that the single character is mapped to the the long option past the first . and the full terminator is the second dot. Of course, there is an even easier method as long as a few rules are observed:

while [ "$#" -gt "0" ]
do
opt="${1//-}"
opt=$(echo "${opt}" | cut -c 1 2>/dev/null)
case $opt in
F) F_FLAG=1;;
f) shift;FILE_ARGUMENT=$1;;
u) usage;;
*) usage; exit 1;;
esac
shift
done

The problem with the last method is the long options are not hard-coded, the first character of the alpha string is cut and used as an option. In other words, --help and --heck will do the same thing. The idea is harmless except no options can be mixed and matched. Generally speaking, not having a --help and --heck valid in the same script or program should be avoided if possible.

Options in Perl

With no case statement built in, doing options parsing in Perl can be a little tricky. Using the same example from the shell code above a simple options parser might look like: [ 1 ]

while ( my $arg = shift @ARGV ) {
if ( $arg eq '-F' ) {
$F_FLAG = 1;
} elsif ( $arg eq '-f' ) {
$FILE_ARGUMENT = shift @ARGV;
} elsif ( $arg eq '-u' ) {
usage();
} else {
usage();
exit 1;
}
}

Relative to the shell, Perl seems a bit heavy handed in the amount of work needed. In Perl the options for handling are almost limitless. Associative arrays, hashes, arrays or just plain scalars arranged a certain way could be used.

Of course, another great thing about Perl is how simplistic string operations are handled. Using a method similar to the last shell method above can simplify the code a great deal:

for (my $argc = 0; $argc <= @ARGV; $argc++) {
$opt = $ARGV[$argc];
$opt =~ s/--//; # Get rid of 2 dashes
$opt =~ s/-//; # Get rid of 1 dash
$opt = substr($opt,0,1); # cut the first char
if ($opt eq 'F') {
$F_FLAG=1;
} elsif ($opt eq 'f') {
$FILE_ARGUMENT=$ARGV[++$argc];
} elsif ($opt eq 'u') {
usage();
} else {
usage();
exit 1;
}
}

Of course, the same two problems from the shell-code which cuts out the first alphanumeric exists; no two long options can start with the same letter and there is no verification of long options. Not unlike the shell, a simple list can be used to verify that long options are valid, following is an example sub routine:

...
my @valid_optlongs=("setflag", "file", "usage");
my @valid_optshort=("F", "f", "u");
...
sub parseopt{
my ($opt) = shift;

$opt =~ s/--//; # Get rid of 2 dashes
$opt =~ s/-//; # Get rid of 1 dash

if (scalar($opt) > 1) {
for ($i = 0; $i < @valid_optlongs; $i++) {
if ($opt eq $valid_optlongs[$i]) {
return $valid_optshort[$i];
}
}
} else {
return $opt;
}
}

Essentially instead of just trimming out the first valid alphanumeric, if the option is a long option check it against the list of valid long options and return the matching single byte option the long option correlates to.

Ultimately, using the getopt module should be done if it is available, why reinvent the wheel? Here is an example of using the Getopt module:

use Getopt::Std;
...
getopt ('f:uF');

die "Usage: $0 [ -f filename -u ]\n"
unless ( $opt_f or $opt_u );

if ($opt_f) {
my $filename = shift @ARGV;
} elsif ($opt_u) {
usage();
exit 0;
}

Definitely shorter and compact.

Parsing Options in C

The oldest high level programming language - not unlike Perl - has many different approaches a programmer can take without using libraries:

int
main(argc, argv)
int argc;
char *argv[];
{
if (argc < 2) {
printf("usage: %s number-of-execs sbrk-size job-name\n",
argv[0]);
exit(1);
}
....


int main (argc, argv) {
for (c = 0; c <=argc; c++) {
if (argc[c] == 'F') {
F_FLAG=1
...

libc offers up two levels of built in options handling, one for single options and one for long options. Since the options handling routines are in modern implementation, the examples will use GNU's version.

Short Options in C

...
#include <getopt.h>
...
int main (int argc, char **argv)
{
int c;
char * file;

while ((c = getopt(argc, argv, "F:f:u:")) != -1) {
switch (c) {
case 'F':
F_FLAG=1
break;
case 'f':
file = optarg;
break;
case 'u':
usage();
return 0;
break;
default:
usage();
return 1;
break;
}
}

Far more succinct than what may have happened using the previous C examples which would have been pretty spaghetti'd. Long options are even more interesting. The GNU C library internally handles assignment of long options by using the single alpha as the key inside of a data structure:

...
#include <getopt.>
...
int main(int argc, char **argv)
while (1)
{
static struct option long_options[] =
{
{"setflag", no_argument, 0, 'F' },
{"file", required_argument, 0, 'f' },
{"usage", no_argument, 0, 'u' },
{0,0,0,0} /* This is a filler for -1 */
};

int option_index = 0;

c = getopt_long (argc, argv, "F:f:u:", long_options, &option_index);

if (c == -1) break;

switch (c) {
case 'F':
F_FLAG=1;
break;
case 'f':
file = optarg;
break;
case 'u':
usage();
return 0;
break;
default:
usage();
return 1;
break;
}
}

Short, sweet and to the point.

Summary

Sometimes parsing can be extremely simple, adding long options and flag setting to the mix can be daunting when writing from the ground up, luckily libraries and modules exist to help along the way.

Footnotes

  1. Special thanks to Matt Mr. Muskrat Musgrove for suggesting showing the Perl Getopt module and writing some nice examples of well formed code. The first example belongs to Matt.

References



'unix and linux' 카테고리의 다른 글

CentOS, Red hat Enterprise Edition 단상  (0) 2008.06.05
서비스 장애  (0) 2008.05.03
rsync FAQ  (0) 2008.04.10
ssh 로그인할 때, 암호 안물어보게 하기  (0) 2008.03.28
Redhat 리눅스 버젼 보기  (0) 2008.03.28
Posted by '김용환'
,

rsync FAQ

unix and linux 2008. 4. 10. 20:06

 

rsync에 대한 FAQ에 대한 내용이다.

 

 

 

http://samba.anu.edu.au/rsync/issues.html

 

current issues and debugging

  1. Q: Rsync appears hung -- what should I do?

    A: When experiencing a hang or freeze please gather the following information before killing the rsync process:

    • The state of the send/receive queues shown with netstat on the two ends.
    • The system call that each of the 3 processes is stuck in (use truss on solaris, strace on Linux, etc.).

    See the "rsync-debug" script below for an example of how to grab strace information from the remote rsync process(es). If you need help, send email to the mailing list.

  2. Q: Why does my chrooted rsync daemon crash when doing an LDAP lookup for a user or group?

    A: There is a bug in some LDAP libraries (e.g. Fedora Core 3) where it crashes when someone looks up a name from inside a chrooted process (one that does not contain copies of the libraries to perform the lookup). This is a bug that the LDAP libraries will need to fix, and is out of rsync's hands. You can work around the problem by using the --numeric-ids option, turning chroot off, or getting rid of LDAP lookups.

  3. Q: Why does my transfer die with something like the following error?

    rsync: error writing 4 unbuffered bytes - exiting: Broken pipe
    rsync error: error in rsync protocol data stream (code 12) at io.c(463)
    

    or

    rsync: connection unexpectedly closed (24 bytes read so far)
    rsync error: error in rsync protocol data stream (code 12) at io.c(342)
    

    A: This error tells you that the local rsync was trying to talk to the remote rsync, but the connection to that rsync is now gone. The thing you must figure out is why, and that can involve some investigative work.

    If the remote rsync is a daemon, your first step should be to look at the daemon's log file to see if it logged an error explaining why it aborted the transfer.

    Beginning with version 2.6.3, rsync now does a better job of retreiving the error from the remote process than older versions of rsync, so you may wish to try upgrading and see if you now get sent the error message from the remote rsync.

    There are several common causes for a remote rsync process going away:

    • The destination disk is full (remember that you need at least the size of the largest file that needs to be updated available in free disk space for the transfer to succeed).
    • An idle connection caused a router or remote-shell server to close the connection.
    • A network error caused the connection to be dropped.
    • The remote rsync executable wasn't found.
    • Your remote-shell setup isn't working right or isn't "clean" (i.e. it is sending spurious text to rsync).

    If you think the problem might be an idle connection getting closed, you might be able to work around the problem by using a --timeout option (newer rsyncs send keep-alive messages during lulls). You can also configure ssh to send keep-alive messages when using Protocol 2 (look for KeepAlive, ServerAliveInterval, ClientAliveInterval, ServerAliveCountMax, and ClientAliveCountMax). You can also avoid some lulls by switching from --delete (aka --delete-before) to --del (aka --delete-during).

    If you can't figure out why the failure happened, there are steps you can take to debug the situation. One way is to create a shell script on the remote system such as this one named "rsync-debug". You would use the script like this:

    rsync -av --rsync-path=/some/path/rsync-debug HOST:SOURCE DEST
    rsync -av --rsync-path=/some/path/rsync-debug SOURCE HOST:DEST
    

    This script enables core dumps and also logs all the OS system calls that lead up to the failure to a file in the /tmp dir. You can use the resulting files to help figure out why the remote rsync failed.

    If you are rsyncing directly to an rsync daemon (without using a remote-shell transport), the above script won't have any effect. Instead, halt the current daemon and run a debug version with core-dumps enabled and (if desired) using a system-call tracing utility such as strace, truss, or tusc. For strace, you would do it like this (the -f option tells strace to follow the child processes too):

    ulimit -c unlimited
    strace -f rsync --daemon --no-detach 2>/tmp/rsync-$$.out
    

    Then, use a separate window to actually run the failing transfer, after which you can kill the debug rsync daemon (pressing Ctrl-C should do it).

    If you are using rsync under inetd, I'd suggest temporarily disabling that and using the above daemon approach to debug what is going on.

  4. Q: Why does my connection to an rsync daemon (using the "::" syntax) fail immediately with an error like the following?

    rsync: connection unexpectedly closed (24 bytes read so far)
    rsync error: error in rsync protocol data stream (code 12) at io.c(342)
    

    A: Older rsync daemons (before 2.6.3) were unable to return errors that were generated during the option-parsing phase of the transfer. Look in the logfile on the server to see if an error was reported, such as a "refused" option, an option that the server rsync doesn't support (e.g. perhaps links are not supported by the server), or some other failure (such as trying to send data to a read-only module). Upgrading the version of rsync that is running as a daemon to at least 2.6.3 will allow these errors to get returned to all rsync clients, old or new alike.

  5. Q: Why doesn't --dry-run (-n) show all the changed directories?

    A: This was a bug in versions prior to 2.6.4. Upgrade both rsync versions (or at least the receiving side).

  6. Q: Aren't there more issues than this?

    A: Yes. You can find some of them in the TODO file or search the bugzilla database.


<FORM action="http://www.google.com/custom" method="get" target="_top">
<INPUT type="hidden" value="samba.org" name="domains"></INPUT> <INPUT maxLength="255" size="31" value="rsync " name=q></INPUT> <INPUT type="submit" value="Search" name="sa"></INPUT>
 
<INPUT type="radio" value="" name=sitesearch></INPUT> Search WWW <INPUT type="radio" CHECKED value="samba.org" name="sitesearch"></INPUT> Search samba.org
<INPUT type="hidden" value="pub-1444957896811922" name="client"></INPUT> <INPUT type="hidden" value="1" name="forid"></INPUT> <INPUT type="hidden" value="ISO-8859-1" name="ie"></INPUT> <INPUT type="hidden" value="ISO-8859-1" name="oe"></INPUT> <INPUT type="hidden" value="GALT:#008000;GL:1;DIV:#336699;VLC:663399;AH:center;BGC:FFFFFF;LBGC:FFFFFF;ALC:0000FF;LC:0000FF;T:000000;GFNT:0000FF;GIMP:0000FF;LH:60;LW:470;L:http://samba.org/samba/images/samba_banner.gif;S:http://samba.org/;FORID:1;" name="cof"></INPUT> <INPUT type="hidden" value="en" name="hl"></INPUT>
</FORM>

 

'unix and linux' 카테고리의 다른 글

서비스 장애  (0) 2008.05.03
option parsing - bash, perl, c  (0) 2008.04.15
ssh 로그인할 때, 암호 안물어보게 하기  (0) 2008.03.28
Redhat 리눅스 버젼 보기  (0) 2008.03.28
Why I love Perl  (0) 2008.02.20
Posted by '김용환'
,

 

이야...

 

출처 : http://www.debian.org/devel/passwordlessssh.ko.html

 

  • 자신의 컴퓨터에서 ssh-keygen(1)을 실행하고 암호를 물으면 그냥 엔터를 칩니다.
    비밀 열쇠와 공개 열쇠가 생성됩니다. 예전 SSH 버전을 사용한다면 ~/.ssh/identity~/.ssh/identity.pub에, 새 버전이라면 ~/.ssh/id_rsa~/.ssh/id_rsa.pub에 저장됩니다.
  • 다음으로 공개 열쇠 파일의 내용은 원격 사이트의 ~/.ssh/authorized_keys에 추가합니다(파일의 모드는 600이어야 합니다).
    자신이 개발자이고 이 열쇠를 사용해 debian.org에 접근하고 싶다면 개발자 데이터베이스에서 자신의 열쇠를 모든 데비안 장비에 전달하게 할 수 있습니다. LDAP 게이트웨이 문서를 보기 바랍니다..
  • 'unix and linux' 카테고리의 다른 글

    option parsing - bash, perl, c  (0) 2008.04.15
    rsync FAQ  (0) 2008.04.10
    Redhat 리눅스 버젼 보기  (0) 2008.03.28
    Why I love Perl  (0) 2008.02.20
    bash 스트링 조작하기  (0) 2008.01.18
    Posted by '김용환'
    ,

    커널 보기.

    uname -a

     

    리눅스 설치된 redhat 버젼 보기

    cat /etc/redhat-release
    Red Hat Linux release 9 (Shrike)


    cat /etc/redhat-release
    Red Hat Enterprise Linux ES release 4 (Nahant Update 6)

    'unix and linux' 카테고리의 다른 글

    rsync FAQ  (0) 2008.04.10
    ssh 로그인할 때, 암호 안물어보게 하기  (0) 2008.03.28
    Why I love Perl  (0) 2008.02.20
    bash 스트링 조작하기  (0) 2008.01.18
    고급 Bash 스크립팅 가이드  (0) 2008.01.18
    Posted by '김용환'
    ,

    Why I love Perl

    unix and linux 2008. 2. 20. 08:24

     

     

    재미있는 펄 이야기~~~

    해보시면 안다!!! 펄 공부는 잼있다~

     

    http://aplawrence.com/Unixart/loveperl.html

     

    Why I love Perl

    This article is written for people who have at least some experience writing shell scripts or who have at least a basic understanding of another programming or scripting language. To understand it, you will need to have Perl installed so that you can test these ideas for yourself and see what happens.

    I'm a fairly recent convert to Perl, having only started using it a few years ago. Switching to something new is always somewhat uncomfortable; there's new syntax to learn, and sometimes whole new ways of doing things. That was certainly the case with Perl, but the pain was offset by the sheer joy of being able to do so many formerly clumsy tasks so simply and elegantly.


     

    Let's dispose of one thing first: I'm not a Perl expert. I'm not an expert at anything- there's just too many things in the world that catch my attention that I can never spend the time necessary to become really proficient at anything. So I am a Perl dabbler: I write a lot of my scripts with it, but I don't for a minute pretend that these are shining examples of Perl at its best.

    However, I have learned a few things, and if you are getting ready to start using Perl, you might find my experiences useful.

    If you haven't yet installed Perl on your SCO system, use your Skunkware CD or get it from Skunkware. Perl usually installs automatically on Linux systems.

    SCO 5.0.6 now includes Perl, and free or low cost Perl ports for Windows are easily found on the web.

    Those wonderful <>'s

    Let's start with a really simple program that just emulates "cat".


     


    #!/usr/bin/perl5
    while (<>) {
      print $_;
    }


    Never mind that "$_" for now; we'll get to that later. For now, just accept that it's the line read. See those <> inside the ()'s? That's the entire magic. That will read data from standard input or from a file given on the command line. That means you can use this as a filter or give it an argument; all of these do the same thing:


     


    cat.pl < somefile 
    cat somefile | cat.pl 
    cat.pl somefile


    That's pretty cool all by itself. Most languages would make you jump through hoops to do just that. But here's the most wonderful part: you can give it multiple filenames


     


    cat.pl file1 file2 file3


    and those magic <>'s will just keep on reading with absolutely no effort on your part. If you don't need to, there's no reason to pay any attention at all to the arguments; Perl handles them for you.

    If you do need to know when one file closes and another opens, the "eof" command will tell you. Try this with multiple files:


     


    #!/usr/bin/perl5
    while (<>) {
      print $_;
      print "--------------------------\n" if eof;
    }


    You can even get the file names if you want them:


     


    #!/usr/bin/perl5
    while (<>) {
      print $_;
      print "--- End of $ARGV ----\n" if eof;
    }


    Are you starting to like this? It gets better. Those angle brackets have more magic: they can read an entire file in one gulp. You can do this, for example:


     


    #!/usr/bin/perl5
    @files=<>;
    print @files;


    Everything got read into "@files", which is an array. Here we just printed it, but there's much more you can do.

    There's more magic in those angle brackets, too. Take a look at this little snippet:


     


    while (<[A-Z]*/*.html [a-e]*.html [g-z]*.html>) {
    ...
    }


    That loops through the names of files matched by the wildcards. What could be easier?

    What if you actually want to open a specific file? Still easy:


     


    open(MYFILE,".profile") or die "Can't open .profile";
    while (<MYFILE>) {
    ...
    }


    That "open" isn't limited to files. Here's something you'll see a lot of:


     


    open(MAIL,"|/usr/bin/mail myaddress\@mydomain.com");
    print MAIL "Special message from a Perl program";
    close MAIL;


    In general, Perl goes out of its way to make things easy for you. Look at this sequence:


     


    open(INFOFILE,"totalclicks");
    $totalclicks=<INFOFILE>;
    open(INFOFILE,"totalhits");
    $totalhits=<INFOFILE>;
    open(INFOFILE,"costperyear");
    $costperyear=<INFOFILE>;


    Did you notice that I didn't bother to "close INFOFILE"? Perl assumes that if you are opening the same filehandle again, you must want to close the file you had open previously, so it just does it- no whining, no crashing out, no nagging.

    That's true throughout the entire language. As another example, Perl makes no hard and fast distinction betwwen numbers and strings that look like numbers. If you have "713" in a variable, you can treat it as a number or a string and Perl will do the right thing:


     


    $whatisit="713";
    $whatisit++;
    print $whatisit;
    # prints 714
    print "\n";
    $whatisit .= " apples";
    print $whatisit;
    # prints '714 apples'
    print "\n";
    $whatisit++;
    print $whatisit;
    # back to just a number again: 715
    print "\n";


    Easy arrays

    Perl has two kinds of arrays, and you are going to love them. The first kind is the traditional type you might know from Basic or C; it's indexed by numbers. This should make sense to anyone who's worked with arrays in any other language:


     


    @month=("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
    print "$month[11]\n";
    # prints Dec (array starts at 0, which is Jan)


    The other kind of array is a "hash". If you know "awk", you already know about these, but if not, this might give you the idea:


     


    %names= (
    "scotest" => "Unix Skills Test",
    "linuxtest" => "Linux Skills Test",
    "quickppp" => "PPP HOW-TO",
    "ipfilter" => "IPFILTER Firewalls",
    );
    print $names{"scotest"};


    At first, this is confusing, because we refer to the array in two different ways, using "@month" for the whole array and "$month[somenumber]" for a particular element. Hashes are worse, because that uses "%arrayname" when we're referring to the whole thing and "$arrayname{some_element}" for one element (notice the squiggly brackets).

    Here's how I remembered the difference when I first started Perl. Square brackets are "square", or "conservative"- so they are the old, traditional arrays. An element is "at" a particular position in such an array, so "@" is its type. "Hash", on the other hand is all ground up- the brackets get distorted by the grinding, so they are squiggly. And if you use your imagination to squish an "@" symbol, you might get a "%".

    None of that helps with learning to use the "$" sign when you want an element. You'll just have to get used to it.

    If that was all there is to arrays, they'd be useful, but Perl gives you some great ways to loop through them. Traditional, numerically indexed arrays are easy, of course. But how do you run through all the elements in a hash array?


     


    foreach (%names ) {
      print "$_\n";
    }


    That's all it takes. It works, but it's a little strange, and not very useful (try it). Of course, Perl has a better way:


     


    foreach (keys %names ) {
      print "$_ is $names{$_}\n";
    }


    That's better, but this is better yet:


     


    foreach (sort keys %names ) {
      print "$_ is $names{$_}\n";
    }


    And how about this?


     


    foreach (reverse sort keys %names ) {
      print "$_ is $names{$_}\n";
    }


    Pattern Matching

    Perl's pattern matching is an absolute joy. It can be a little confusing at first, but once the concept clicks in, it becomes natural, and so much easier than anything else you've ever worked with. If you are used to "sed" and"awk", Perl is those tools super-charged. Let's look through a file for a certain word:


     


    while (<>) {
      print "$_" if /\bhello\b/i;
    }


    That "\b" is a neat little helper. It says that "hello" has to be at a "word boundary", which is not necessarily a space. It could be the beginning of a line, the end, or it could follow punctuation. The little "i" says "ignore case". There's more little modifiers like that, but I'm not going to cover them here.

    In this case, the /\bhello\b/ tests against "$_" (which I still haven't fully explained). It can test any variable, though:


     


    foreach $line (@files) {
      print $line if $line =~ /hello/i;
    }


    That weird little "=~" is what makes the match test work against $line. Did you notice the "do something if.." way of testing? You could also do:


     


    if ( $line =~ /hello/i ) {
      print $line;
    }


    There's another thing to notice about that: I didn't use "$_". That's because it isn't available when I specifically say "foreach $line": the "$_" appears only when I don't specify a variable (as I did in the earlier examples).

    There are many places where you can just assume "$_" will be available, but you do have to watch out for things like this that disable it.

    Substitutions

    Add an "s" in front and it starts working like "sed":


     


    $line =~ s/hello/greetings/;


    will change "hello" to "greetings" if it occurs in $line. But it's really much more powerful than that. I don't have the space in this article to go into the incredible power of Perl's pattern matching and substitution features, but believe me, it is just incredible. I'll just give one little example without explanation:

    Some of you may use "uncgi" for your cgi scripts. That's fine, but it's so easy to do in Perl. Here's what I use for POST scripts:


     


    #!/usr/bin/perl5
    $query=""; # simply to prevent warning in read about uninitialized
    read (STDIN,$query,$ENV{'CONTENT_LENGTH'});
    @pairs=split(/&/,$query);
    foreach $keyv (@pairs) {
            ($key,$value)=split(/=/,$keyv);
            $value =~ tr/+/ /;
            $value =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack ("C",hex($1))/eg;
            $formdata{$key}=$value;
            }
    foreach $key (keys %formdata) {
     $$key=$formdata{$key};
    }


    That works very much like "uncgi". For example, if you have a form element called "search", its value will be in "$search", etc. It's that "$$key=" that pulls off that trick. But it's that


     


            $value =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack ("C",hex($1))/eg;


    that does most of the work. As I said, I'm not going to explain it here, but if you know what the POST method delivers to your script, you should really appreciate the power.

    (Actually- it's even easier, because what you'd really use is the CGI module which means you don't have to worry about any of it, but this shows you how you COULD do such things.)

    For scripts that get passed arguments on the command line, it's even easier: Perl stores all the arguments in an array called @ARGV. Therefor, you can refer to $ARGV[0] to get the first, you can extract the arguments and remove them from the array with something like


     


    $first=shift @ARGV;
    $second=shift @ARGV;


    Or you can just run through the whole thing with


     


    foreach (@ARGV) {
      print "$_;\n";
    }


    or:


     


    print "$p\n" while ($p = shift @ARGV);


    That's Perl: there's a dozen ways to do it, and you use what makes sense at the time.

    Split and join

    You have a file like this that you want to extract elements from:


     


    field|more|stuff
    one|this|that
    two|the other|more data


    Piece of cake:


     


    while (<>) {
     @stuff=split /\|/, $_;
     print "$stuff[0] $stuff[2]\n";
    }


    The opposite of split is join:


     


    while (<>) {
     @stuff=split /\|/, $_;
     $f=join "+",@stuff;
     print "$f\n";
    }


    That changes the "|" separators to "+"'s.

    So much more

    You could write useful programs with just the few little ideas you've learned here. That, is, in fact, one of the other things I love about Perl: you can get started using it with a very minimal understanding and with lots of things still confusing you. Many of the early Perl programs I wrote did things like this:


     


    print "<p align=\"center\"><a href=\"/index.html\">
    <img src=\"/image21.gif\" BORDER=0 WIDTH=69 
    HEIGHT=76></a> <br><p align=center><font size=2>
    <b>A.P. Lawrence Home</b></font>";


    There's a lot of confusing quoting in that print statement, and (of course) there are easier ways to do it:


     


    print <<EOF;
    <p align="center"><a href="/index.html">
    <img src="/image21.gif" BORDER=0 WIDTH=69 
    HEIGHT=76></a> <br><p align=center><font size=2>
    <b>A.P. Lawrence Home</b></font>
    EOF


    Or even:


     


    print q?<p align="center"><a href="/index.html">
    <img src="/image21.gif" BORDER=0 WIDTH=69 
    HEIGHT=76></a> <br><p align=center><font size=2>
    <b>A.P. Lawrence Home</b></font>?;


    If you want to get started with Perl, you'll need some books. See these for starters:

    Learning Perl
    Programming Perl
    Perl Cookbook
    Advanced Perl

    You may want to look at some of the other programming articles here; several of them are written with Perl:

    Posted by '김용환'
    ,

    9.2. Manipulating Strings

    Bash supports a surprising number of string manipulation operations. Unfortunately, these tools lack a unified focus. Some are a subset of parameter substitution, and others fall under the functionality of the UNIX expr command. This results in inconsistent command syntax and overlap of functionality, not to mention confusion.

    String Length

    ${#string}

    expr length $string

    expr "$string" : '.*'

       1 stringZ=abcABC123ABCabc
       2 
       3 echo ${#stringZ}                 # 15
       4 echo `expr length $stringZ`      # 15
       5 echo `expr "$stringZ" : '.*'`    # 15


    Example 9-10. Inserting a blank line between paragraphs in a text file

       1 #!/bin/bash
       2 # paragraph-space.sh
       3 
       4 # Inserts a blank line between paragraphs of a single-spaced text file.
       5 # Usage: $0 <FILENAME
       6 
       7 MINLEN=45        # May need to change this value.
       8 #  Assume lines shorter than $MINLEN characters
       9 #+ terminate a paragraph.
      10 
      11 while read line  # For as many lines as the input file has...
      12 do
      13   echo "$line"   # Output the line itself.
      14 
      15   len=${#line}
      16   if [ "$len" -lt "$MINLEN" ]
      17     then echo    # Add a blank line after short line.
      18   fi  
      19 done
      20 
      21 exit 0

    Length of Matching Substring at Beginning of String

    expr match "$string" '$substring'

    $substring is a regular expression.

    expr "$string" : '$substring'

    $substring is a regular expression.

       1 stringZ=abcABC123ABCabc
       2 #       |------|
       3 
       4 echo `expr match "$stringZ" 'abc[A-Z]*.2'`   # 8
       5 echo `expr "$stringZ" : 'abc[A-Z]*.2'`       # 8

    Index

    expr index $string $substring

    Numerical position in $string of first character in $substring that matches.

       1 stringZ=abcABC123ABCabc
       2 echo `expr index "$stringZ" C12`             # 6
       3                                              # C position.
       4 
       5 echo `expr index "$stringZ" 1c`              # 3
       6 # 'c' (in #3 position) matches before '1'.

    This is the near equivalent of strchr() in C.

    Substring Extraction

    ${string:position}

    Extracts substring from $string at $position.

    If the $string parameter is "*" or "@", then this extracts the positional parameters, [1] starting at $position.

    ${string:position:length}

    Extracts $length characters of substring from $string at $position.

       1 stringZ=abcABC123ABCabc
       2 #       0123456789.....
       3 #       0-based indexing.
       4 
       5 echo ${stringZ:0}                            # abcABC123ABCabc
       6 echo ${stringZ:1}                            # bcABC123ABCabc
       7 echo ${stringZ:7}                            # 23ABCabc
       8 
       9 echo ${stringZ:7:3}                          # 23A
      10                                              # Three characters of substring.

    If the $string parameter is "*" or "@", then this extracts a maximum of $length positional parameters, starting at $position.

       1 echo ${*:2}          # Echoes second and following positional parameters.
       2 echo ${@:2}          # Same as above.
       3 
       4 echo ${*:2:3}        # Echoes three positional parameters, starting at second.

    expr substr $string $position $length

    Extracts $length characters from $string starting at $position.

       1 stringZ=abcABC123ABCabc
       2 #       123456789......
       3 #       1-based indexing.
       4 
       5 echo `expr substr $stringZ 1 2`              # ab
       6 echo `expr substr $stringZ 4 3`              # ABC

    expr match "$string" '\($substring\)'

    Extracts $substring at beginning of $string, where $substring is a regular expression.

    expr "$string" : '\($substring\)'

    Extracts $substring at beginning of $string, where $substring is a regular expression.

       1 stringZ=abcABC123ABCabc
       2 #       =======	    
       3 
       4 echo `expr match "$stringZ" '\(.[b-c]*[A-Z]..[0-9]\)'`   # abcABC1
       5 echo `expr "$stringZ" : '\(.[b-c]*[A-Z]..[0-9]\)'`       # abcABC1
       6 echo `expr "$stringZ" : '\(.......\)'`                   # abcABC1
       7 # All of the above forms give an identical result.

    expr match "$string" '.*\($substring\)'

    Extracts $substring at end of $string, where $substring is a regular expression.

    expr "$string" : '.*\($substring\)'

    Extracts $substring at end of $string, where $substring is a regular expression.

       1 stringZ=abcABC123ABCabc
       2 #                ======
       3 
       4 echo `expr match "$stringZ" '.*\([A-C][A-C][A-C][a-c]*\)'`    # ABCabc
       5 echo `expr "$stringZ" : '.*\(......\)'`                       # ABCabc

    Substring Removal

    ${string#substring}

    Strips shortest match of $substring from front of $string.

    ${string##substring}

    Strips longest match of $substring from front of $string.

       1 stringZ=abcABC123ABCabc
       2 #       |----|
       3 #       |----------|
       4 
       5 echo ${stringZ#a*C}      # 123ABCabc
       6 # Strip out shortest match between 'a' and 'C'.
       7 
       8 echo ${stringZ##a*C}     # abc
       9 # Strip out longest match between 'a' and 'C'.

    ${string%substring}

    Strips shortest match of $substring from back of $string.

    ${string%%substring}

    Strips longest match of $substring from back of $string.

       1 stringZ=abcABC123ABCabc
       2 #                    ||
       3 #        |------------|
       4 
       5 echo ${stringZ%b*c}      # abcABC123ABCa
       6 # Strip out shortest match between 'b' and 'c', from back of $stringZ.
       7 
       8 echo ${stringZ%%b*c}     # a
       9 # Strip out longest match between 'b' and 'c', from back of $stringZ.


    Example 9-11. Converting graphic file formats, with filename change

       1 #!/bin/bash
       2 #  cvt.sh:
       3 #  Converts all the MacPaint image files in a directory to "pbm" format.
       4 
       5 #  Uses the "macptopbm" binary from the "netpbm" package,
       6 #+ which is maintained by Brian Henderson (bryanh@giraffe-data.com).
       7 #  Netpbm is a standard part of most Linux distros.
       8 
       9 OPERATION=macptopbm
      10 SUFFIX=pbm          # New filename suffix. 
      11 
      12 if [ -n "$1" ]
      13 then
      14   directory=$1      # If directory name given as a script argument...
      15 else
      16   directory=$PWD    # Otherwise use current working directory.
      17 fi  
      18   
      19 #  Assumes all files in the target directory are MacPaint image files,
      20 # + with a ".mac" suffix.
      21 
      22 for file in $directory/*    # Filename globbing.
      23 do
      24   filename=${file%.*c}      #  Strip ".mac" suffix off filename
      25                             #+ ('.*c' matches everything
      26 			    #+ between '.' and 'c', inclusive).
      27   $OPERATION $file > "$filename.$SUFFIX"
      28                             # Redirect conversion to new filename.
      29   rm -f $file               # Delete original files after converting.   
      30   echo "$filename.$SUFFIX"  # Log what is happening to stdout.
      31 done
      32 
      33 exit 0
      34 
      35 # Exercise:
      36 # --------
      37 #  As it stands, this script converts *all* the files in the current
      38 #+ working directory.
      39 #  Modify it to work *only* on files with a ".mac" suffix.

    Substring Replacement

    ${string/substring/replacement}

    Replace first match of $substring with $replacement.

    ${string//substring/replacement}

    Replace all matches of $substring with $replacement.

       1 stringZ=abcABC123ABCabc
       2 
       3 echo ${stringZ/abc/xyz}           # xyzABC123ABCabc
       4                                   # Replaces first match of 'abc' with 'xyz'.
       5 
       6 echo ${stringZ//abc/xyz}          # xyzABC123ABCxyz
       7                                   # Replaces all matches of 'abc' with # 'xyz'.

    ${string/#substring/replacement}

    If $substring matches front end of $string, substitute $replacement for $substring.

    ${string/%substring/replacement}

    If $substring matches back end of $string, substitute $replacement for $substring.

       1 stringZ=abcABC123ABCabc
       2 
       3 echo ${stringZ/#abc/XYZ}          # XYZABC123ABCabc
       4                                   # Replaces front-end match of 'abc' with 'XYZ'.
       5 
       6 echo ${stringZ/%abc/XYZ}          # abcABC123ABCXYZ
       7                                   # Replaces back-end match of 'abc' with 'XYZ'.

    9.2.1. Manipulating strings using awk

    A Bash script may invoke the string manipulation facilities of awk as an alternative to using its built-in operations.


    Example 9-12. Alternate ways of extracting substrings

       1 #!/bin/bash
       2 # substring-extraction.sh
       3 
       4 String=23skidoo1
       5 #      012345678    Bash
       6 #      123456789    awk
       7 # Note different string indexing system:
       8 # Bash numbers first character of string as '0'.
       9 # Awk  numbers first character of string as '1'.
      10 
      11 echo ${String:2:4} # position 3 (0-1-2), 4 characters long
      12                                          # skid
      13 
      14 # The awk equivalent of ${string:pos:length} is substr(string,pos,length).
      15 echo | awk '
      16 { print substr("'"${String}"'",3,4)      # skid
      17 }
      18 '
      19 #  Piping an empty "echo" to awk gives it dummy input,
      20 #+ and thus makes it unnecessary to supply a filename.
      21 
      22 exit 0

    9.2.2. Further Discussion

    For more on string manipulation in scripts, refer to Section 9.3 and the relevant section of the expr command listing. For script examples, see:

    1. Example 12-6

    2. Example 9-15

    3. Example 9-16

    4. Example 9-17

    5. Example 9-19

    Notes

    [1]

    This applies to either command line arguments or parameters passed to a function.

    'unix and linux' 카테고리의 다른 글

    Redhat 리눅스 버젼 보기  (0) 2008.03.28
    Why I love Perl  (0) 2008.02.20
    고급 Bash 스크립팅 가이드  (0) 2008.01.18
    rotatelog.c 버그 수정해놓기  (0) 2008.01.16
    getopt() 함수  (0) 2008.01.16
    Posted by '김용환'
    ,