이 기사에서는 필터를 사용하여 텍스트를 조작하기 위해 복잡한 파이프라인을 빌드할 수 있도록 하는 필터에 대한 소개를 제공한다. 여기서는 다른 태스크 중에서도 텍스트를 표시하고 정렬하고 단어와 행을 계수하고 문자를 변환하는 방법에 대해 살펴본다. 또한 스트림 편집기 sed의 사용 방법도 알아본다.
이 기사에서는 다음 주제에 대해 살펴본다.
- 출력을 수정하기 위해 텍스트 유틸리티 필터를 통해 텍스트 파일 및 출력 스트림 전송하기
- GNU textutils 패키지에 있는 표준 UNIX 명령 사용하기
- 편집기 sed를 사용하여 복잡한 변경사항을 텍스트 파일로 스크립트화하기
이 기사는 Junior Level Administration(LPIC-1) 기초 과정 시험 중 Topic 103에 있는 Objective 103.2를 대비하는 데 도움이 된다. 이 목표의 가중치는 3이다. 이 기사에 있는 자료는 2009년 4월 기초 과정 시험의 목표에 해당한다. 최종 요구사항을 위해서는 목표를 항상 참조해야 한다.
텍스트 필터링은 텍스트의 입력 스트림을 가져와서 출력 스트림에 전송하기 전에 텍스트에 대한 일부 변환을 수행하는 프로세스이다. 입력 또는 출력은 파일로부터 제공될 수 있지만 Linux 및 UNIX® 환경에서는 필터링이 한 명령의 출력이 다음 명령에 대한 입력으로 사용되도록 파이프 또는 경로 재지정되는 명령의 파이프라인을 구성하여 수행되는 경우가 가장 많다. 파이프와 경로 재지정은 스트림, 파이프 및 경로 재지정(시리즈 로드맵에서 찾을 수 있음)에서 더 자세하게 다루고 지금은 | 및 > 연산자를 사용한 파이프 및 기본 출력 경로 재지정에 대해 살펴보자.
스트림은 애플리케이션으로부터 기본 디바이스의 세부사항을 숨기는 라이브러리 함수를 사용하여 읽거나 쓸 수 있는 바이트의 시퀀스에 불과하다. 동일한 프로그램이 스트림을 사용하여 디바이스에 종속된 방식으로 터미널, 파일 또는 네트워크 소켓에 대한 읽기 또는 쓰기를 수행할 수 있다. 최신 프로그래밍 환경 및 쉘에서는 세 가지 표준 I/O 스트림을 사용한다.
- stdin은 명령에 입력을 제공하는 표준 입력 스트림이다.
- stdout은 명령의 출력을 표시하는 표준 출력 스트림이다.
- stderr은 명령의 오류 출력을 표시하는 표준 오류 스트림이다.
입력은 사용자가 명령에 제공하는 매개변수로부터 제공될 수 있고 출력은
터미널에 표시될 수 있다. 많은 텍스트 처리 명령(필터)이 표준 입력 스트림 또는
파일로부터 입력을 가져올 수 있다. 명령의 출력(command1)을 필터에 대한
입력(command2)으로 사용하려면 파이프 연산자(|)를 사용하여 명령을 연결한다.
Listing 1에서는 echo의 출력을 파이프로 연결하여
적은 단어 목록을 정렬하는 방법을 보여 준다.
Listing 1. echo의 출력을 정렬의 입력에 파이프로 연결하기
[ian@echidna ~]$ echo -e "apple\npear\nbanana"|sort
apple
banana
pear
|
두 명령 모두 옵션 또는 인수를 가질 수 있다. 또한 |를 사용하여 파이프라인에 있는 두 번째 명령의 출력을 세 번째 명령으로 경로 재지정하는 식으로 경로를 재지정할 수 있다. 각각 기능이 제한된 명령의 긴 파이프라인을 구성하는 것은 Linux 및 UNIX에서 일반적으로 태스크를 달성하는 방식이다. 또한 파일 이름의 위치에 있는 하이픈(-)이 명령에 대한 인수로 사용되어 입력이 파일이 아니라 stdin으로부터 제공되어야 함을 의미하는 경우도 종종 보게 될 것이다.
여러 명령의 파이프라인을 작성하고 터미널에서 출력을 볼 수 있는 것도 좋지만 파일에 출력을 저장하려고 하는 경우도 있다. 출력 경로 재지정 연산자(>)를 사용하여 이를 수행한다.
이 섹션의 나머지 부분에서는 일부 작은 파일을 사용하므로 lpi103-2라는
디렉토리를 작성한 후 해당 디렉토리로 디렉토리를 변경하자. 그런 다음
>를 사용하여 echo 명령의 출력을 text1이라는
파일로 경로를 재지정한다. 이 내용은 모두 Listing 2에 표시되어 있다.
출력이 해당 파일로 경로 재지정되었기 때문에 해당 출력은 터미널에
표시되지 않는다는 것에 유의한다.
Listing 2. 명령의 출력을 파일로 경로 재지정하기
[ian@echidna ~]$ mkdir lpi103-2
[ian@echidna ~]$ cd lpi103-2
[ian@echidna lpi103-2]$ echo -e "1 apple\n2 pear\n3 banana" > text1
|
파이프 연결 및 경로 재지정을 위한 몇 가지 기본 도구에 대해 살펴봤으니 일반적인 UNIX 및 Linux 텍스트 처리 명령 및 필터 중 일부에 대해 알아보자. 이 섹션에서는 기본 기능 중 일부에 대해 보여 준다. 적절한 매뉴얼 페이지를 확인하여 이러한 명령에 대해 자세히 알아본다.
test1 파일을 작성했으니 이 파일의 내용을 확인하려고 할 수 있다.
cat(concatenate의 약어) 명령을
사용하여 파일의 컨텐츠를 stdout에 표시한다. Listing 3에서는
위에서 작성한 파일의 컨텐츠를 확인한다.
Listing 3. cat을 사용하여 파일 컨텐츠 표시하기
[ian@echidna lpi103-2]$ cat text1
1 apple
2 pear
3 banana
|
파일 이름을 지정하지 않거나 -을 파일 이름으로 지정하는 경우 cat
명령은 stdin에서 입력을 가져온다. 이를 출력 경로 재지정과 함께 사용하여
Listing 4와 같이 다른 텍스트 파일을 작성해 보자.
Listing 4. cat을 사용하여 텍스트 파일 작성하기
[ian@echidna lpi103-2]$ cat >text2
9 plum
3 banana
10 apple
|
Listing 4에서 cat은 파일의 끝까지 계속 stdin으로부터
읽는다. Ctrl-d(Ctrl을 누른 상태로 d를 누름) 조합을
사용하여 파일의 끝이라는 신호를 보낸다. 이는 bash 쉘에서 종료하기 위해
필요한 키 조합과 동일하다. 탭 키를 사용하여 열에 있는 과일 이름을 정렬한다.
cat이 concatenate의 약어라고 한 것을 기억하는가? cat을
사용하여 여러 파일을 연결하여 함께 표시할 수 있다. Listing 5에서는 방금 작성한 두 파일을 보여 준다.
Listing 5. cat으로 두 파일 연결하기
[ian@echidna lpi103-2]$ cat text*
1 apple
2 pear
3 banana
9 plum
3 banana
10 apple
|
cat을 사용하여 이 두 텍스트 파일을 표시하면
다르게 정렬되어 있는 것을 알게 된다. 원인을 알아보려면 파일에 있는
제어 문자를 살펴봐야 한다. 제어 문자는 제어 문자 자체의 일부 표시를
표시하는 대신 텍스트 표시 출력에서 작동되므로 이러한 특수 문자를
찾아서 해석할 수 있게 하는 형식으로 파일을 덤프해야 한다.
GNU 텍스트 유틸리티에는 이러한 용도를 위한 od(Octal Dump)
명령이 포함되어 있다.
파일 오프셋의 기수를 제어하는 -A 옵션과 표시되는
파일 컨텐츠의 양식을 제어하는 -t와 같은 od에
대한 여러 가지 옵션이 있다. 기수는 o(기본값인 8진수), d(10진수), x(16진수) 또는
n(오프셋이 표시되지 않음)으로 지정될 수 있다. 출력을 8진수, 10진수, 16진수,
부동 소수점, 백슬래시 이스케이프가 있는 ASCII 또는 이름 지정된 문자(nl(줄 바꾸기),
ht(가로 탭) 등)로 표시할 수 있다. Listing 6에서는 text2 예제 파일을 덤프하는 데
사용할 수 있는 형식 중 일부를 보여 준다.
Listing 6. od를 사용하여 파일 덤프하기
[ian@echidna lpi103-2]$ od text2
0000000 004471 066160 066565 031412 061011 067141 067141 005141
0000020 030061 060411 070160 062554 000012
0000031
[ian@echidna lpi103-2]$ od -A d -t c text2
0000000 9 \t p l u m \n 3 \t b a n a n a \n
0000016 1 0 \t a p p l e \n
0000025
[ian@echidna lpi103-2]$ od -A n -t a text2
9 ht p l u m nl 3 ht b a n a n a nl
1 0 ht a p p l e nl
|
참고:
cat의-A옵션은 탭과 행 끝의 위치를 확인하는 대체 방법을 제공한다. 자세한 정보는 매뉴얼 페이지를 참조한다.- 자체 text2 파일에 탭 대신 공백이 표시되는 경우 나중에 이 기사에 나오는 Expand, unexpand 및 tr을 참조하여 파일에서 탭과 공백 사이를 전환하는 방법을 확인한다.
- 메인프레임 백그라운드를 가진 경우에는 다른 유틸리티 세트의 일부인 hexdump 유틸리티에 관심이 있을 수 있다. 이 유틸리티에 대해서는 여기서 다루지 않으므로 매뉴얼 페이지를 확인한다.
샘플 파일은 매우 작지만 작은 부분으로 분할해야 하는 큰 파일이 있는 경우가
있다. 예를 들어, DVD를 만들 수 있는 사용자에게 메일을 통해 전송하기 위해
CD에 작성할 수 있도록 큰 파일을 CD 크기의 청크로 분할할 수 있다. split
명령은 파일을 쉽게 다시 작성하기 위해 cat 명령을
사용할 수 있는 것과 같이 이를 수행한다. 기본적으로 split
명령 수행 결과 발생하는 파일의 이름에는 접미어 'aa', 'ab', 'ac', ..., 'ba', 'bb' 등이
뒤따라오는 접두어 'x'가 지정된다. 옵션을 사용하여 이러한 기본값을 변경할 수 있다.
또한 출력 파일의 크기와 결과 파일에 전체 행과 바이트 개수 중 어느 것이
포함되는지도 제어할 수 있다.
Listing 7에서는 출력 파일에 서로 다른 접두어를 사용하여 두 텍스트 파일을
분할하는 것을 보여 준다. text1을 최대 2개의 행이 포함된 파일로 분할하고
text2를 최대 18바이트가 포함된 파일로 분할한다. 그런 다음 cat을
사용하여 일부 조각을 개별적으로 표시하고 이 기사의 기본 파일 및 디렉토리 관리(시리즈
로드맵에서 찾을 수 있음)에서 설명하는 와일드카드 사용을 통해 전체 파일을 표시한다.
Listing 7. split 및 cat을 사용하여 분할 및 재결합하기
[ian@echidna lpi103-2]$ split -l 2 text1
[ian@echidna lpi103-2]$ split -b 17 text2 y
[ian@echidna lpi103-2]$ cat yaa
9 plum
3 banana
1[ian@echidna lpi103-2]$ cat yab
0 apple
[ian@echidna lpi103-2]$ cat y* x*
9 plum
3 banana
10 apple
1 apple
2 pear
3 banana
|
yaa라는 분할 파일은 줄 바꾸기 문자로 끝나지 않았기 때문에 cat을
사용하여 이를 표시한 후 프롬프트가 오프셋되었다는 것에 유의한다.
Cat은 전체 파일을 표시한다. 위 예제와 같은
작은 파일의 경우 이는 문제가 없지만 큰 파일이 있다고 가정해 보자. 먼저
wc(Word Count) 명령을 사용하여
파일 크기를 확인하려고 할 수 있다. wc 명령은
파일에 있는 행, 단어 및 바이트의 수를 표시한다. 또한 ls -l를
사용하여 바이트 수를 찾을 수 있다. Listing 8에서는 wc의
출력과 두 텍스트 파일의 긴 형식 디렉토리 목록을 보여 준다.
Listing 8. 텍스트 파일에 wc 사용하기
[ian@echidna lpi103-2]$ ls -l text*
-rw-rw-r--. 1 ian ian 24 2009-08-11 14:02 text1
-rw-rw-r--. 1 ian ian 25 2009-08-11 14:27 text2
[ian@echidna lpi103-2]$ wc text*
3 6 24 text1
3 6 25 text2
6 12 49 total
|
옵션을 사용하면 wc의 출력을 제어하거나
최대 행 길이와 같은 기타 정보를 표시할 수 있다. 세부사항은 매뉴얼
페이지를 참조한다.
두 명령을 사용하면 파일의 첫 번째 파트(헤드) 또는 마지막 파트(테일)를
표시할 수 있다. 이러한 명령은 head 명령과 tail
명령이다. 이들 명령은 필터로 사용되거나 파일 이름을 인수로 사용할 수
있다. 기본적으로 이들 명령은 파일 또는 스트림의 처음(또는 마지막) 10행을
표시한다. Listing 9에서는 dmesg 명령을 사용하여
부팅 메시지를 표시하고 이와 함께 wc, tail 및
head를 사용하여 791개의 메시지가 있음을 발견한 후
이 중 마지막 10개 메시지를 표시하고 마지막으로 끝에서 15번째부터 시작하여
6개의 메시지를 표시한다. 이 출력에서 일부 행은 잘렸다(...로 표시됨).
Listing 9. wc, head 및 tail을 사용하여 부트 메시지 표시하기
[ian@echidna lpi103-2]$ dmesg|wc
791 5554 40186
[ian@echidna lpi103-2]$ dmesg | tail
input: HID 04b3:310b as /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2.4/3-2.4:1.0/input/i
nput12
generic-usb 0003:04B3:310B.0009: input,hidraw1: USB HID v1.00 Mouse [HID 04b3:310b] on us
b-0000:00:1a.0-2.4/input0
usb 3-2.4: USB disconnect, address 11
usb 3-2.4: new low speed USB device using uhci_hcd and address 12
usb 3-2.4: New USB device found, idVendor=04b3, idProduct=310b
usb 3-2.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
usb 3-2.4: configuration #1 chosen from 1 choice
input: HID 04b3:310b as /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2.4/3-2.4:1.0/input/i
nput13
generic-usb 0003:04B3:310B.000A: input,hidraw1: USB HID v1.00 Mouse [HID 04b3:310b] on us
b-0000:00:1a.0-2.4/input0
usb 3-2.4: USB disconnect, address 12
[ian@echidna lpi103-2]$ dmesg | tail -n15 | head -n 6
usb 3-2.4: USB disconnect, address 10
usb 3-2.4: new low speed USB device using uhci_hcd and address 11
usb 3-2.4: New USB device found, idVendor=04b3, idProduct=310b
usb 3-2.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
usb 3-2.4: configuration #1 chosen from 1 choice
input: HID 04b3:310b as /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2.4/3-2.4:1.0/input/i
nput12
|
tail은 일반적으로 행 수가 1인 -f
옵션을 사용하여 파일을 따르는 데도 일반적으로 사용된다. 파일에
출력을 생성 중인 백그라운드 프로세스가 있을 때 체크인하여 진행 상황을
확인하려는 경우 이를 사용할 수 있다. 이 모드에서 tail은
사용자가 Ctrl-c를 사용하여 취소할 때까지 실행되어 파일에 작성될 때
행을 표시한다.
text1 및 text2 파일을 작성할 때 탭 문자가 포함된 text2를 작성했다.
가끔 탭을 공백과 스왑하거나 그 반대를 수행하려고 할 수 있다.
expand 및 unexpand
명령이 이를 수행한다. 두 명령의 -t 옵션을 사용하면
탭 정지를 설정할 수 있다. 단일 값은 해당 간격으로 반복되는 탭을 설정한다.
Listing 10에서는 text2에서 탭을 단일 간격과 text2의 테스트를 정렬 해제하는
unexpand 및 expand의
예측할 수 없는 또다른 시퀀스로 펼치는 방법을 보여 준다.
Listing 10. expand 및 unexpand 사용하기
[ian@echidna lpi103-2]$ expand -t 1 text2
9 plum
3 banana
10 apple
[ian@echidna lpi103-2]$ expand -t8 text2|unexpand -a -t2|expand -t3
9 plum
3 banana
10 apple
|
안타깝게도 unexpand를 사용하려면 탭으로 변환할
둘 이상의 공백이 필요하기 때문에 text1에 있는 공백은 unexpand를
사용하여 탭으로 대체할 수 없다. 하지만 하나의 세트(set1)에 있는
문자를 또다른 세트(set2에 있는 해당 문자로 변환하는 tr
명령을 사용할 수 있다. Listing 11에서는 tr을
사용하여 공백을 탭으로 변환하는 방법을 보여 준다. tr은
순수하게 필터이므로 사용자는 cat 명령을 사용하여
이에 대한 입력을 생성한다. 또한 이 예제에서는 text2 파일과 tr의
출력을 연결할 수 있도록 -을 사용하여 cat에 대한 표준 입력을
나타내는 것을 보여 준다.
목록 11. tr 사용하기
[ian@echidna lpi103-2]$ cat text1 |tr ' ' '\t'|cat - text2
1 apple
2 pear
3 banana
9 plum
3 banana
10 apple
|
마지막 두 예제에서 진행된 상황을 확실하게 이해하지 못한 경우에는
od를 사용하여 파이프라인의 각 단계를
차례로 종료한다. 예:
cat text1 |tr ' ' '\t' | od -tc
pr 명령은 출력을 위해 파일의 형식을 지정하는 데
사용된다. 기본 머리글에는 파일 이름과 파일 작성 날짜 및 시간이 페이지 번호 및
비어 있는 바닥글 2행과 함께 포함되어 있다. 다중 파일 또는 표준 입력 스트림에서
출력이 작성되면 파일 이름 및 작성 날짜 대신 현재 날짜 및 시간이 사용된다.
파일을 열에 나란히 출력하고 옵션을 통해 형식화의 다수 측면을 제어할 수 있다.
평소대로 세부사항은 매뉴얼 페이지를 참조한다.
nl 명령은 행에 번호를 지정하며 이는 파일
출력 시 편리할 수 있다. cat 명령의 -n
옵션을 사용하여 행에 번호를 지정할 수도 있다. Listing 12에서는 텍스트
파일을 출력하는 방법과 text2에 번호를 지정하여 text1과 함께 나란히
출력하는 방법을 보여 준다.
목록 12. 출력을 위해 번호 지정 및 형식화하기
[ian@echidna lpi103-2]$ pr text1 | head
2009-08-11 14:02 text1 Page 1
1 apple
2 pear
3 banana
[ian@echidna lpi103-2]$ nl text2 | pr -m - text1 | head
2009-08-11 15:36 Page 1
1 9 plum 1 apple
2 3 banana 2 pear
3 10 apple 3 banana
|
텍스트 형식화를 위한 또다른 유용한 도구로는 여백에 맞도록 텍스트를 형식화하는
fmt 명령이 있다. 여러 개의 짧은 행을 결합할 수도
있고 긴 행을 분할할 수도 있다. Listing 13에서는 문장을 네 번이나 입력하는
수고를 덜기 위해 !#:* 히스토리 기능의 변형을
사용하여 하나의 긴 텍스트 행으로 text3을 작성한다. 또한 행 당 하나의
단어만 있는 text4도 작성한다. 그런 다음 cat을 사용하여
형식화되지 않은 상태로 표시한다(행의 끝을 나타내기 위해 표시된 '$' 문자 포함).
마지막으로 fmt를 사용하여 최대 너비인 60자로
형식화한다. 추가 옵션에 대한 세부사항은 매뉴얼 페이지를 참조한다.
Listing 13. 최대 행 길이로 형식화하기
[ian@echidna lpi103-2]$ echo "This is a sentence. " !#:* !#:1->text3
echo "This is a sentence. " "This is a sentence. " "This is a sentence. ">text3
[ian@echidna lpi103-2]$ echo -e "This\nis\nanother\nsentence.">text4
[ian@echidna lpi103-2]$ cat -et text3 text4
This is a sentence. This is a sentence. This is a sentence. $
This$
is$
another$
sentence.$
[ian@echidna lpi103-2]$ fmt -w 60 text3 text4
This is a sentence. This is a sentence. This is a sentence. This is another sentence.
|
sort 명령은 시스템의 로케일(LC_COLLATE)에 대한
조합 순서를 사용하여 입력을 정렬한다. sort 명령은
이미 정렬된 파일을 병합하고 파일이 정렬되어 있는지 여부를 검사할 수도 있다.
Listing 14에서는 text1에서 공백을 탭으로 변환한 후 sort
명령을 사용하여 두 텍스트 파일을 정렬하는 것에 대해 보여 준다. 정렬 순서가
문자순이므로 결과에 놀랄 수 있다. 다행히도 sort
명령은 숫자 값이나 문자 값을 기준으로 정렬할 수 있다. 이 선택사항을
전체 레코드에 지정하거나 각 필드에 지정할 수 있다. 다른 필드
분리 문자를 지정하는 경우가 아니면 필드는 공백이나 탭에 의해 구분된다.
Listing 14의 두 번째 예제에서는 첫 번째 필드는 숫자를 기준으로 정렬하고
두 번째 필드는 조합 순서(영문자순)를 기준으로 정렬하는 것을 보여 준다.
또한 -u 옵션을 사용하여 중복 행을 제거하고
고유한 행만 보존하는 것도 보여 준다.
Listing 14. 문자 및 숫자 정렬
[ian@echidna lpi103-2]$ cat text1 | tr ' ' '\t' | sort - text2
10 apple
1 apple
2 pear
3 banana
3 banana
9 plum
[ian@echidna lpi103-2]$ cat text1|tr ' ' '\t'|sort -u -k1n -k2 - text2
1 apple
2 pear
3 banana
9 plum
10 apple
|
두 정렬 키(이 예제에서는 k1n과 k2) 모두에 대해 고유성 테스트가 수행되었기 때문에 "apple"이라는 과일이 포함된 두 행이 여전히 있다는 것에 유의한다. 단계를 수정하거나 위 파이프라인에 추가하여 두 번째 'apple'이 발생하지 않도록 하는 방법에 대해 생각해 보자.
uniq라는 또다른 명령은 중복 행 제거를 제어하는
또다른 방법을 제공한다. uniq 명령은 일반적으로
정렬된 파일에서 작동하고 정렬 여부에 관계없이 파일에서 연속된 동일한
행을 제거한다. uniq 명령은 일부 필드를 무시할
수도 있다. Listing 15에서는 두 번째 필드(과일 이름)를 사용하여 두 텍스트
파일을 정렬한 후 두 번째 필드에서부터 동일한 행을 제거한다(즉, uniq로
테스트할 때는 첫 번째 필드를 건너뜀).
Listing 15. uniq 사용하기
[ian@echidna lpi103-2]$ cat text1|tr ' ' '\t'|sort -k2 - text2|uniq -f1
10 apple
3 banana
2 pear
9 plum
|
여기서는 조합 순서를 기준으로 정렬이 수행되었으므로 uniq는
"1 apple" 대신 "10 apple" 행을 제공한다. 키 필드 1에 숫자 정렬을
추가하여 이를 변경하는 방법을 알아보자.
이제 텍스트 데이터에서 필드를 처리하는 세 개의 추가 명령에 대해 살펴보자.
이러한 명령은 표 형식의 데이터를 처리하는 데 특히 유용하다. 첫 번째 명령은
텍스트 파일에서 필드를 추출하는 cut 명령이다.
기본 필드 구분 기호는 탭 문자이다. Listing 16에서는 cut을
사용하여 text2의 두 열을 분리하고 공백을 출력 구분 기호로 사용하는 데 이는
각 행에 있는 탭을 공백으로 변환하는 색다른 방법이다.
Listing 16. cut 사용하기
[ian@echidna lpi103-2]$ cut -f1-2 --output-delimiter=' ' text2
9 plum
3 banana
10 apple
|
paste 명령은 pr 명령이
-m 옵션을 사용하여 파일을 병합하는 것과 비슷한
방식으로 둘 이상의 파일에서 제공된 행을 나란히 붙여넣는다. Listing 17에서는
두 텍스트 파일을 붙여넣기한 결과를 보여 준다.
Listing 17. 파일 붙여넣기
[ian@echidna lpi103-2]$ paste text1 text2
1 apple 9 plum
2 pear 3 banana
3 banana 10 apple
|
이러한 예제에서는 단순한 붙여넣기를 보여 주지만 paste는
여러 가지 다른 방법으로 하나 이상의 파일로부터 데이터를 붙여넣을 수 있다.
세부사항은 매뉴얼 페이지를 참조한다.
마지막 필드 조작 명령은 일치하는 필드를 기반으로 파일을 결합하는 join이다.
파일은 결합 필드에서 정렬되어야 한다. text2는 숫자 순서로 정렬되어 있지
않기 때문에 text2를 정렬하면 join 명령이 일치하는 결합 필드(이 예제에서는
값 3이 포함된 필드)가 있는 두 행을 결합한다.
Listing 18. 결합 필드를 사용하여 파일 결합하기
[ian@echidna lpi103-2]$ sort -n text2|join -j 1 text1 -
3 banana banana
join: file 2 is not in sorted order
|
그렇다면 무엇이 잘못되었을까? sort 및 uniq 섹션에서 문자 및 숫자 정렬에 대해 살펴본 내용을 기억해 본다. 결합은 로케일의 조합 순서에 따라 일치하는 문자에 대해 수행된다. 결합은 필드가 모두 동일한 길이가 아닌 한 숫자 필드에서 작동하지 않는다.
여기서는 -j 1 옵션을 사용하여 각 파일의
필드 1에서 결합을 수행했다. 결합에 사용할 필드는 각 파일에 대해 별도로
지정될 수 있다. 예를 들어, 한 파일의 필드 3과 다른 파일의 필드 10을 기반으로
결합을 수행할 수 있다.
또한 두 번째 필드(과일 이름)에서 text 1을 정렬하여 새 파일인 text5를 작성한 후 공백을 탭으로 대체해 보자. 그런 다음 두 번째 필드에서 text2를 정렬하고 각 파일의 두 번째 필드를 결합 필드로 사용하여 이를 text 5와 결합하는 경우에는 두 개의 일치(apple과 banana)가 있어야 한다. Listing 19에서는 이러한 결합을 보여 준다.
Listing 19. 결합 필드를 사용하여 파일 결합하기
[ian@echidna lpi103-2]$ sort -k2 text1|tr ' ' '\t'>text5
[ian@echidna lpi103-2]$ sort -k2 text2 | join -1 2 -2 2 text5 -
apple 1 10
banana 3 3
|
Sed는 stream editor이다. 여러 developerWorks 기사와 다수의 서적에서 sed에 대해 살펴볼 수 있다(참고자료 참조). Sed는 매우 강력하며 sed가 달성할 수 있는 태스크는 사용자의 상상에 의해서만 제한된다. 이 간략한 소개에서는 sed에 대한 관심은 불러 일으키지만 완전하고 광범위한 내용을 다루지는 않는다.
지금까지 살펴본 많은 텍스트 명령과 마찬가지로 sed는 필터 역할을 하거나 파일로부터 입력을 가져올 수 있다. 출력은 표준 출력 스트림에 제공된다. Sed는 입력의 행을 패턴 공간에 로드하고 sed 편집 명령을 패턴 공간의 컨텐츠에 적용한 후 패턴 공간을 표준 출력에 작성한다. Sed는 패턴 공간에 있는 여러 행을 결합할 수 있고 파일에 쓰거나 선택된 출력만 쓰거나 전혀 쓰기를 수행하지 않을 수 있다.
Sed는 정규식 구문을 사용하여 패턴 공간에서 선택적으로 텍스트를 검색하여 대체하고 편집 명령 세트에 의해 조작이 수행되어야 하는 테스트 행을 제어한다. 정규식에 대해서는 기사의 정규식을 사용하여 텍스트 파일 검색하기(시리즈 로드맵에서 찾을 수 있음)에서 더 자세하게 다룬다. 보류 버퍼(hold buffer)는 텍스트의 임시 스토리지를 제공한다. 보류 버퍼(hold buffer)는 패턴 공간을 대체하거나 패턴 공간에 추가되거나 패턴 공간과 교환될 수 있다. Sed에는 제한된 명령 세트만 포함되어 있지만 이들은 정규식 구문 및 보류 버퍼(hold buffer)와 결합되어 놀라운 기능을 제공한다. Sed 명령 세트는 일반적으로 sed 스크립트라고 부른다.
Listing 20에서는 세 가지 단순 sed 스크립트를 보여 준다. 첫 번째 스크립트에서는
s(substitute) 명령을 사용하여 각 행에서 소문자
'a'를 대문자로 대체한다. 이 예제에서는 첫 번째 'a'만 대체하므로
두 번째 예제에서는 'g'(global) 플래그를 추가하여 sed가 모든 발생을
변경하도록 한다. 세 번째 스크립트에서는 행을 삭제하는 d(delete)
명령을 소개한다. 예제에서는 2라는 주소를 사용하여 2행만 삭제되어야 함을
나타낸다. 여기서는 세미콜론(;)을 사용하여 명령을 분리하고 두 번째 스크립트에
사용한 것과 동일한 글로벌 대체를 사용하여 'a'를 'A'로 대체한다.
Listing 20. Sed 스크립트 시작하기
[ian@echidna lpi103-2]$ sed 's/a/A/' text1
1 Apple
2 peAr
3 bAnana
[ian@echidna lpi103-2]$ sed 's/a/A/g' text1
1 Apple
2 peAr
3 bAnAnA
[ian@echidna lpi103-2]$ sed '2d;$s/a/A/g' text1
1 apple
3 bAnAnA
|
개별 행에 대한 작동 외에도 sed는 일정 범위의 행에서 작동될 수 있다.
범위의 시작과 끝은 쉼표(,)로 분리되고 행 번호, 정규식 또는 파일의 끝에
해당하는 달러 부호($)로 지정될 수 있다. 하나의 주소 또는 일정 범위의
주소가 있는 경우 중괄호({와 }) 사이에 여러 명령을 그룹화하여 이러한
명령이 해당 범위에 의해 선택된 행에서만 작동하도록 할 수 있다. Listing 21에서는
글로벌 대체를 파일의 마지막 두 행에만 적용하는 두 가지 방법에 대해
보여 준다. 또한 스크립트에 다중 명령을 추가하는 -e
옵션의 사용에 대해서도 보여 준다.
Listing 21. Sed 주소
[ian@echidna lpi103-2]$ sed -e '2,${' -e 's/a/A/g' -e '}' text1
1 apple
2 peAr
3 bAnAnA
[ian@echidna lpi103-2]$ sed -e '/pear/,/bana/{' -e 's/a/A/g' -e '}' text1
1 apple
2 peAr
3 bAnAnA
|
Sed 스크립트도 파일에 저장될 수 있다. 실제로 자주 사용되는 스크립트에
이를 수행하려고 할 것이다. 앞서 tr 명령을
사용하여 text1의 공백을 탭으로 변경한 것을 기억한다. 이제 파일에 저장된
sed 스크립트를 사용하여 이를 수행해 보자. 여기서는 echo
명령을 사용하여 파일을 작성한다. Listing 22에 결과가 표시된다.
Listing 22. 한 행으로 된 sed
[ian@echidna lpi103-2]$ echo -e "s/ /\t/g">sedtab
[ian@echidna lpi103-2]$ cat sedtab
s/ / /g
[ian@echidna lpi103-2]$ sed -f sedtab text1
1 apple
2 pear
3 banana
|
Listing 22와 같이 하나의 행으로 된 편리한 sed가 다수 있다. 이들 중 일부에 대한 링크는 참고자료를 참조한다.
최종 sed 예제에서는 = 명령을 사용하여 행 번호를
출력한 후 다시 sed를 통해 결과 출력을 필터링하여 숫자 행에 대한 nl
명령의 효과를 모방한다. Listing 23에서는 =를
사용하여 행 번호를 출력한 후 N 명령을 사용하여
두 번째 입력 행을 패턴 공간으로 읽어오고 마지막으로 패턴 공간에서 두 행
사이의 줄 바꾸기 문자(\n)를 제거한다.
Listing 23. Sed를 사용하여 행 번호 지정하기
[ian@echidna lpi103-2]$ sed '=' text2
1
9 plum
2
3 banana
3
10 apple
[ian@echidna lpi103-2]$ sed '=' text2|sed 'N;s/\n//'
19 plum
23 banana
310 apple
|
우리가 원하던 결과는 아니다. 우리가 원하는 결과는 열에서 숫자를 파일의 행 앞에 있는 일정 공간에 맞추는 것이다. Listing 24에서는 여러 행의 명령(> 보조 프롬프트에 유의)을 입력한다. 예제에 대해 살펴보고 아래의 설명을 참조한다.
Listing 24. Sed를 사용하여 행 번호 지정하기 - 두 번째
[ian@echidna lpi103-2]$ cat text1 text2 text1 text2>text6
[ian@echidna lpi103-2]$ ht=$(echo -en "\t")
[ian@echidna lpi103-2]$ sed '=' text6|sed "N
> s/^/ /
> s/^.*\(......\)\n/\1$ht/"
1 1 apple
2 2 pear
3 3 banana
4 9 plum
5 3 banana
6 10 apple
7 1 apple
8 2 pear
9 3 banana
10 9 plum
11 3 banana
12 10 apple
|
지금까지 수행한 단계는 다음과 같다.
- 먼저
cat을 사용하여 text1 및 text2 파일의 각 사본 2부로부터 12행의 파일을 작성했다. 다른 자리수를 가지고 있지 않는 경우에는 열에서 숫자의 형식을 지정하는 것은 즐거운 작업이 아니다. - bash 쉘은 명령 완료를 위해 탭 키를 사용하므로 실제 탭을 원할 때
사용할 수 있는 고정 탭 문자를 가지고 있으면 편리할 수 있다. 여기서는
echo명령을 사용하여 이를 달성한 후 쉘 변수 'ht'에 문자를 저장한다. - 앞서 한 것과 같이 데이터 행이 뒤따라오는 행 번호가 포함된 스트림을 작성한 후 sed의 두 번째 사본을 통해 필터링한다.
- 두 번째 행을 패턴 공간으로 읽어온다.
- 패턴 공간의 시작 부분(^로 표시됨)에 있는 행 번호에 6개의 공백을 접두어로 지정한다.
- 그런 다음 새 행까지 모든 행을 새 행과 탭 문자 앞의 마지막 6개 문자로 대체한다. 이를 수행하면 출력 행의 처음 6개 열에서 행 번호가 정렬된다. 's' 명령의 왼쪽 부분에서는 '\(' 및 '\)'를 사용하여 오른쪽 부분에 사용할 문자를 표시한다는 것에 유의한다. 오른쪽 부분에서는 이렇게 표시된 첫 번째 세트(이 예제의 유일한 해당 세트)를 \1으로 참조한다. 명령이 큰따옴표(") 사이에 포함되어 있어 $ht에 대해 대체가 발생한다는 것에 유의한다.
Sed의 버전 4에는 info 형식의 문서와 다수의
우수한 예제가 포함되어 있다. 이전 버전인 3.02 버전에는 이러한 내용이
포함되어 있지 않다. GNU sed는 sed --version을
승인하여 버전을 표시한다.
교육
- developerWorks의 LPIC-1 로드맵을 사용하여 2009년 4월 목표를 기반으로 하는 LPIC-1 인증을 준비하는 데 도움을 줄 수 있는 developerWorks 기사를 찾을 수 있다.
- LPIC Program 사이트에서 Linux Professional Institute의 Linux 시스템 관리 인증의 세 가지 레벨에 대한 자세한 목표, 작업 목록 및 샘플 질문을
찾을 수 있다. 특히, LPI exam 101과 LPI exam 102의 2009년 4월 목표를 확인하자. 항상 LPIC Program 사이트를 참조하여 최신 목적을 확인한다.
- developerWorks에 있는 전체 LPI exam prep 시리즈를 검토하여 Linux에 대한 기초 지식을 학습하고 2009년 4월 이전의 초기 LPI 시험 목표를 기반으로 하는
시스템 관리 인증을 준비하자.
- "Basic tasks for
new Linux developers"(developerWorks, 2005년 3월)에서 터미널 창이나 쉘 프롬프트를 여는 방법 등을 학습할 수 있다.
- Linux Documentation Project에는 특히 HOWTO(기술 노하우)를 포함한
다양하고 유용한 문서가 수록되어 있다.
- Sed 예제 시리즈의 Part 1, Part 2 및 Part 3는
sed 스킬을 개발하는 탁월한 방법이다.
- developerWorks
Linux 영역에서는 Linux 개발자에게 도움이 되는 여러 가지 리소스를 제공하고 있으며
가장 인기 있는 기사와 튜토리얼도 볼 수 있다.
- developerWorks에 있는
Linux 팁과
Linux 튜토리얼을 모두 볼 수 있다.
- developerWorks
기술 행사 및 웹 캐스트를 통해 최신 정보를 얻을 수 있다.
제품 및 기술 얻기
- developerWorks에서 직접 다운로드할 수 있는 IBM
시험판 소프트웨어를 사용하여 Linux와 관련된 후속 개발 프로젝트를 구현해 볼 수 있다.
토론
- 포럼에 참여하기.
- 사용자의 개인 프로파일과 사용자 정의 홈 페이지가 제공되는 My
developerWorks community에서는 관심을 가지고 있는 developerWorks의 여러 주제를 추적할 수 있으며 다른 developerWorks 사용자들과 의견을 나눌 수도 있다.
Ian Shields는 developerWorks 리눅스 영역을 위한 리눅스 프로젝트 다수를 수행하고 있다. Shields는 노스 캐롤라이나 주 소재 IBM 리서치 트라이앵글 파크에서 선임 프로그래머로 일한다. Shields는 1973년 시스템 엔지니어로 오스트레일리아, 캔베라에 있는 IBM 사무실에 들어갔으며 캐나다 몬트리얼과 노스 캐롤라이나 주 RTP에서 통신 시스템과 배포 컴퓨팅 부문에서 일해왔다. Shields는 특허 여러 건을 획득했으며, 논문 여러 건을 발표했다. Shields는 순수 수학과 철학 학사 학위를 오스트레일리안 국립 대학에서 받았다. 노스 캐롤라이나 주립 대학에서 컴퓨터 과학 분야를 대상으로 석사와 박사 학위를 받았다. 전자편지 주소는 ishields@us.ibm.com이다.