SED 명령 시작하기 [초보자 안내서]


Unix 도구 상자의 가장 강력한 명령 중 하나인 SED 명령의 실제 예가 포함된 스트림 편집기인 sed를 사용하는 방법을 알아보세요.

Sed는 60년대 말부터 Unix 표준 도구 상자의 일부였습니다. 텍스트 편집기로서 텍스트 파일을 수정하는 데 도움이 됩니다. 그러나 이미 사용해 본 텍스트 편집기와 달리 이는 비대화형 편집기입니다.

즉, 파일에 적용할 변환을 미리 지정하면 도구가 감독 없이 해당 변환을 적용할 수 있다는 의미입니다.

도구의 설계 목표에 대한 가장 좋은 설명은 원본 sed 문서에서 원래 구현의 핵심 개발자인 Lee E. McMahon의 글입니다.

Sed는 UNIX 운영 체제에서 실행되는 비대화형 컨텍스트 편집기입니다. Sed는 다음 세 가지 경우에 특히 유용하도록 설계되었습니다.

  1. 편안한 대화형 편집을 하기에는 너무 큰 파일을 편집하려는 경우

  2. 편집 명령의 순서가 너무 복잡하여 대화형 모드에서 편안하게 입력할 수 없는 경우 모든 크기의 파일을 편집합니다.

  3. 입력을 통해 한 번에 여러 '전역' 편집 기능을 효율적으로 수행합니다.

목표 디자인 (1)과 (3)은 아마도 최신 하드웨어와 관련성이 낮을 수 있지만 두 번째 디자인은 여전히 유효합니다. 개인적인 추가 사항으로 sed는 파일 세트에 동일한 변환을 적용하려는 경우와 같은 반복적인 작업에 특히 적합하다고 말하고 싶습니다.

다음 예제를 통해 기본 SED 명령을 알아보세요.

sed의 강력한 기능을 맛보기 위해 프로젝트의 각 소스 파일 위에 라이선스 헤더를 추가해야 하는 개발자의 사례를 살펴보겠습니다.

linux@handbook:~$ head MIT.LICENSE *.sh
==> MIT.LICENSE <==
-----8<----------------------------------------------------------------
Copyright <YEAR> <COPYRIGHT HOLDER>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

==> script1.sh <==
#!/bin/bash

echo Hello, I\'m the first script

==> script2.sh <==
#!/bin/bash

cat << EOF
Hello, I'm the second script
EOF

각 쉘 스크립트 상단에서 라이센스 파일을 보고 싶을 뿐만 아니라 연도와 저작권 자리 표시자를 실제 값으로 대체하고 싶습니다. 이것이 우리의 첫 번째 사용 사례가 될 것입니다.

참고: 직접 연습하고 싶다면 내 웹사이트에서 샘플 파일을 다운로드할 수 있습니다. 이 기사를 완성하는 비디오를 시청할 수도 있습니다.

1. SED에서 텍스트 바꾸기

내 라이센스 파일에서 자리 표시자를 실제 값으로 바꾸고 싶습니다.

이는 sed substitution 명령에 완벽하게 적합한 작업입니다. 아마도 모든 sed 명령 중에서 가장 유용한 명령일 것입니다.

linux@handbook:~$ sed -e 's/<YEAR>/2018/' MIT.LICENSE  | head -5
-----8<----------------------------------------------------------------
Copyright 2018 <COPYRIGHT HOLDER>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

파이프(|)를 사용하여 sed 명령의 출력을 head 도구에 전달하여 여기에 처음 5줄만 표시했습니다. 하지만 오늘의 특정 주제에서 가장 흥미로운 부분은 s//2018/ 표현식입니다.

Sed는 입력 파일을 한 번에 한 줄씩 처리하여 작동합니다. 각 줄에서 대체(s) 명령은 처음 두 슬래시(//) 사이의 첫 번째 텍스트를 마지막 슬래시 사이의 텍스트로 바꿉니다. 두 개(/2018/). GUI 텍스트 편집기에 있는 검색-바꾸기 기능과 비슷하다고 생각하세요.

여기서 언급할 만한 점은 원본 MIT.LICENSE 파일이 수정되지 않았다는 것입니다. 다음 명령을 사용하여 직접 확인할 수 있습니다.

head -5 MIT.LICENSE

2. 텍스트 교체… 다시

훌륭합니다. 연도 자리 표시자를 교체했습니다. 하지만 교체할 두 번째 제품이 있습니다. 이전 예제를 이해했다면 아마도 다음과 같은 두 번째 sed 표현식을 상상할 수 있을 것입니다.

's/<COPYRIGHT HOLDER>/Sylvain Leroux/'

그런데 그걸 어디에 둘까요? 글쎄, 당신에게는 몇 가지 선택이 있습니다. 리디렉션 개념에 이미 익숙하다면 가장 확실한 방법은 첫 번째 sed 명령의 출력을 sed의 두 번째 인스턴스로 파이프하는 것입니다.

linux@handbook:~$ sed -e 's/<YEAR>/2018/' MIT.LICENSE  |
    sed -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' |
    head -5
----8<----------------------------------------------------------------
Copyright 2018 Sylvain Leroux

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

하지만 우리는 더 잘할 수 있습니다. -e 옵션은 sed 표현식을 도입하므로 그 중 여러 개를 동일한 sed 호출의 일부로 사용할 수 있으며 결과는 동일합니다.

# Pay special attention to the \ at the end of the lines
# specifying the *same* command continues on the
# next line:
sh$ sed -e 's/<YEAR>/2018/'  \
                -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
                MIT.LICENSE |
        head -5

마지막으로, 새 줄로 구분하여 동일한 sed 표현식에서 여러 명령을 지정할 수도 있습니다. 이는 보다 복잡한 sed 프로그램 작성을 시작할 때 특히 유용합니다.

# Pay special attention to the single-quotes and
# backslash placement:
sh$ sed -e 's/<YEAR>/2018/
            s/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        MIT.LICENSE |
    head -5

3. 텍스트 삽입

이제 자리 표시자를 실제 값으로 대체했습니다. 하지만 해당 라이센스 파일을 프로젝트 파일에 삽입하기 전에 아직 수행해야 할 작업이 있습니다. 나중에 쉘 스크립트가 되므로 라이센스의 각 줄은 쉘이 해당 줄을 해석하려고 시도해서는 안 된다는 것을 이해할 수 있도록 옥토소프(#)로 시작해야 합니다.

이를 위해 대체 명령을 다시 사용하겠습니다. 이전에 언급하지 않은 점은 GUI 편집기의 대부분의 검색-바꾸기 기능과 달리 검색 패턴이 반드시 검색할 리터럴 문자열이 아니라는 것입니다. 실제로 이것은 정규식(regex)입니다. 즉, 축어적으로 일치하는 일반 문자 외에도 특별한 의미를 갖는 문자를 사용할 수 있습니다. 예를 들어 캐럿(^)은 줄의 시작을 나타내고 달러 기호($)는 줄의 끝을 나타냅니다. 또는 마지막 예에서처럼 점 -별표(.*)는 0, 1 또는 여러 문자의 시퀀스를 의미합니다. 다른 메타문자도 많이 있지만 지금은 이것으로 충분합니다.

따라서 줄 시작 부분에 텍스트를 삽입하려면 줄 시작 부분을 대체하는 것이 좋습니다. 해당 텍스트로:

linux@handbook:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        MIT.LICENSE | head -5
# -----8<----------------------------------------------------------------
# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the

4. 선택한 라인 지우기

sed의 대체 명령은 매우 다양하여 이를 사용하여 대부분의 텍스트 변환을 표현할 수 있습니다. 예를 들어 라이센스 텍스트의 상단과 하단에 있는 점선을 제거하려면 다음과 같이 작성할 수 있습니다.

linux@handbook:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e 's/^.*----.*$//' \
        MIT.LICENSE | head -5

# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the

나중에 대체된 내용은 모든 텍스트가 빈 문자열로 대체되었습니다.

^

줄의 시작 부분에서 시작

.*

그 뒤에는 0, 1 또는 여러 문자의 시퀀스가 옵니다.

----

그 뒤에 하이픈 4개가 옵니다.

.*

그 뒤에는 0, 1 또는 여러 문자의 시퀀스가 옵니다.

$

줄의 끝이 이어집니다.

즉, 행에 4개의 대시가 포함되어 있다면 전체 줄이 빈 문자열로 대체됩니다. 그러나 빈 줄 자체는 출력에 남아 있으며 빈 줄로 나타납니다.

정확한 요구 사항과 취향에 따라 아래의 대체 솔루션을 고려해 볼 수도 있습니다. 명령의 변경 사항을 정확히 찾아내고 결과에 대한 결과가 무엇인지 직접 확인할 수 있도록 자세히 검토해 보겠습니다.

linux@handbook:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^.*----.*$//' \
        -e 's/^/# /' \
        MIT.LICENSE | head -5

줄을 지우는 데 사용되는 정규 표현식이 너무 복잡하다고 생각되면 다른 sed 기능을 활용할 수도 있습니다. 거의 모든 명령은 명령 이름 앞에 선택적 주소를 사용할 수 있습니다. 존재하는 경우 명령의 범위를 해당 주소와 일치하는 줄로 제한합니다.

linux@handbook:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e '/----/s/^.*$//' \
        MIT.LICENSE | head -5

이제 최신 대체 명령은 연속된 4개의 대시와 일치하는(즉, "포함") 줄에만 적용됩니다. 그리고 일치하는 각 줄에 대해 줄의 시작(^)과 끝($) 사이의 모든 항목(.*)을 다음과 같이 바꿉니다. 빈 문자열(//)

5. 선택한 라인 제거

이전 섹션에서는 일부 텍스트 줄을 지우기 위해 대체 명령을 조정했습니다. 그러나 빈 줄은 그대로 남아 있었습니다. 때로는 이것이 바람직할 때도 있습니다. 때로는 그렇지 않습니다. 후자의 경우 delete 명령을 조사하여 출력에서 전체 줄을 제거할 수 있습니다.

# Below, the redirection '> LICENSE' is used to store
# the result of the sed command into the newly
# created LICENSE file:
linux@handbook:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e '/----/d' \
        MIT.LICENSE > LICENSE
linux@handbook:~$ head -5 LICENSE
# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including

d삭제 명령 이름입니다. s대체 명령 이름인 것과 같습니다. 여기서는 명령 앞에 주소를 지정하여 일치하는 줄만 제거합니다(주소가 없으면 d 명령은 파일의 모든 줄을 삭제합니다).

6. 대문자로 변환

지금까지 우리는 주로 라이센스 파일의 상단에 집중했습니다. 그러나 실제로 문서에 대해 좀 더 자세히 수행하고 싶은 몇 가지 변경 사항이 있습니다. 먼저 제가 무슨 말을 하는지 살펴보겠습니다.

linux@handbook:~$ sed -ne '/The above/,$p' LICENSE
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# The software is provided "as is", without warranty of any kind,
# express or implied, including but not limited to the warranties of
# merchantability, fitness for a particular purpose and noninfringement.
# In no event shall the authors or copyright holders be liable for any
# claim, damages or other liability, whether in an action of contract,
# tort or otherwise, arising from, out of or in connection with the
# software or the use or other dealings in the software.

위 명령에서 -n 옵션을 사용하여 패턴 공간의 자동 인쇄를 비활성화했습니다. 즉, 내가 명시적으로 요청하지 않는 한 sed는 더 이상 출력에 아무것도 인쇄하지 않는다는 의미입니다. 이것이 바로 print(p) 명령을 사용하여 수행하는 작업입니다. p 명령 앞에 단일 주소를 사용하는 대신 범위를 사용하여 "The Above" 텍스트가 포함된 줄과 문서 끝 사이에 텍스트를 표시했습니다. ($).

인쇄 명령은 파일의 일부를 추출해야 할 때 유용할 수 있습니다. 그러나 오늘은 지금 필요한 것이 무엇인지 설명하기 위해 마지막 두 단락을 표시하고 싶었습니다. 라이센스 파일의 전통이므로 소프트웨어가 "있는 그대로" 제공된다는 점을 분명히 밝히고 싶습니다. ” 그래서 저는 마지막 단락(“소프트웨어”로 시작하는)을 모두 대문자로 다시 작성하여 강조하고 싶습니다.

대체 명령의 대체 부분에서 &는 검색 패턴과 일치하는 텍스트로 대체됩니다. \U GNU 확장을 사용하면 대체 문자열의 대소문자를 변경할 수 있습니다.

linux@handbook:~$ sed -i -e '/The software/,$s/.*/\U&/' LICENSE
linux@handbook:~$ cat LICENSE

일반 텍스트에서 s/.*/\U&/는 "모든 텍스트(.*)를 대문자(\U) 버전으로 바꾸는 것을 의미합니다. 자체(&)입니다. 직접 확인해 보도록 하겠습니다. 이제 마지막 단락은 모두 대문자로 작성되어야 합니다. 그런데 -i 플래그로 인해 변경 사항이 LICENSE 파일에 직접 적용되었음을 알 수 있습니다.

이에 대해서는 다음 섹션에서 자세히 살펴보겠습니다. 그 동안에는 여러분이 원하는 대로 해당 명령을 연습하고 수정하도록 해드립니다. 자신의 취향에 맞는 라이선스 파일이 있으면 프로젝트의 각 소스 파일 앞에 이를 어떻게 포함할지 살펴보겠습니다.

7. 텍스트 파일 삽입

여기서 복잡한 명령을 기대했다면 실망할 것입니다. 파일을 다른 명령에 삽입하는 것은 매우 간단합니다.

sed -i -e '1r LICENSE' script1.sh
cat script1.sh

여기서 볼 수 있는 두 가지 사항은 다음과 같습니다.

  1. r LICENSE 표현식은 현재 처리 중인 파일에 외부 파일을 읽고 삽입하는 명령입니다. 여기에는 입력 파일의 라인 1에만 일치하는 주소인 숫자 1가 접두어로 붙습니다.

  2. -i 옵션을 사용하면 제자리에 있는 파일을 변경할 수 있습니다. 이는 sed가 출력을 저장하기 위해 씬 뒤에서 임시 파일을 생성하고, 처리가 완료되면 원본 파일을 수정된 파일로 대체한다는 의미입니다.

'-i' 옵션의 흥미로운 부작용은 명령줄에서 여러 파일 이름을 지정할 수 있으며 sed가 각 파일에 독립적으로 동일한 변환을 적용한다는 것입니다.

sed -i -e '1r LICENSE' *.sh

8. 미래로 돌아 가기

sed 명령의 마지막 예시로 몇 년이 지나 지금이 2024년 1월 1일이라고 가정해 보겠습니다. 모든 파일의 저작권 표시를 업데이트해야 합니다. 프로젝트 파일이 생성된 시기에 따라 여러 가지 사용 사례가 있습니다. 따라서 저작권 고지는 다음 두 가지 형식 중 하나를 따라야 합니다.

Copyright 2023

작년에 생성된 파일의 경우

Copyright 2018-2023

작년 이전에 생성된 파일의 경우

확장된(-E) 정규식을 사용하여 두 가지 사용 사례를 한 번에 캡처할 수 있습니다. 여기서 실제로 사용할 유일한 "확장" 항목은 괄호입니다.

sed -i -Ee 's/Copyright (....)(-....)?/Copyright \1-2024/' *.sh

*.sh 파일의 저작권 표시를 수동으로 수정한 다음 다양한 사용 사례에서 위의 명령을 실행하여 작동 방식을 확인하는 것이 좋습니다.

검색 패턴에서 다음과 같이 말하면 결국 이해하는 데 도움이 될 수 있습니다. Copyright::은 문자 그대로 일치하는 텍스트입니다. (… .):: 네 개의 임의 문자와 일치하는 캡처 그룹을 정의합니다. 연도의 네 자리 숫자를 바랍니다. (-… .)?:: 대시와 네 개의 임의 문자가 이어지는 캡처 그룹을 정의합니다. 끝에 있는 물음표는 그룹이 선택 사항임을 나타냅니다. 입력 라인에 있을 수도 있고 없을 수도 있습니다.

대체 문자열에서: Copyright::은 그대로 복사되는 리터럴 텍스트입니다. \1::은 첫 번째 캡처 그룹의 콘텐츠입니다. -2024::은 그대로 복사되는 리터럴 텍스트입니다.

시간을 들여 명령을 직접 확인했다면 이전 표에 설명된 사용 사례에 해당 규칙을 적용하는지 확인해야 하며 다음과 같은 결과를 얻게 됩니다.

Matching text \1 \2 Replacement string
Copyright 2023 2023 Copyright 2023-2024
Copyright 2018-2023 2018 -2023 Copyright 2018-2024

SED 가이드를 마무리하려면

우리는 여기서 단지 표면만 긁었을 뿐입니다. sed 도구는 그보다 훨씬 더 강력합니다. 그러나 4개의 명령(s, p, di)만 본 경우에도 몇 가지 기본 정규식 구문(^, $, ., ?.*) 귀하는 이미 많은일상적인 문제를 해결하기에 충분한 지식을 갖고 있습니다.

저는 약간의 도전으로 튜토리얼을 마무리하는 것을 좋아하므로 여러분에게 제안하는 것은 다음과 같습니다. 지원 자료를 다운로드한 경우 프로젝트 디렉토리에서 hello.c라는 파일을 찾을 수 있습니다. 다음은 기본 C 프로그램의 소스 파일입니다.

linux@handbook:~$ ls
hello.c  MIT.LICENSE  script1.sh  script2.sh
linux@handbook:~$ gcc hello.c -o hello
linux@handbook:~$ ./hello sylvain
Hello sylvain
linux@handbook:~$ cat hello.c

소스 파일에 이미 일부 주석이 있습니다. 이를 C 프로그래밍 언어의 주석 구문의 예로 사용하여 sed 명령을 사용하여 MIT 라이센스를 hello.c 소스 파일에 삽입할 수 있습니까? 하나 또는 여러 개의 sed 명령을 사용할 수 있고, sed 명령의 출력을 다른 명령으로 파이프할 수 있으며, 원하는 경우 임시 파일을 사용할 수 있지만 허용되지 않습니다. sed 이외의 다른 명령을 사용하려면 물론, 라이센스를 삽입한 후에도 C 소스 파일은 계속 컴파일되어야 합니다!

이제 그 작은 문제에 대해 생각해 보도록 하겠습니다. 해당 기사와 관련 비디오를 재미있게 즐기셨기를 바랍니다. sed에 대해 더 알고 싶다면 댓글 섹션을 사용하여 알려주세요!