sed에 변수를 전달할 때 큰따옴표를 사용해야 한다는 것을 알고 있습니다. 따라서 sed를 사용하여 줄 번호가 지정된 파일의 줄을 표시할 때:
sed '894!d' cloud.cpp
작동하지만 행 번호 894를 sed에 변수로 전달하고 싶기 때문에 다음을 시도했습니다.
lnum=894
sed "$lnum!d" cloud.cpp
그러나 동일한 구문을 사용하는 작은따옴표도 작동하지 않습니다.
sed "894!d" cloud.cpp
그렇다면 이 경우 어떻게 변수를 sed에 전달할 수 있습니까?
답변1
변수에 숫자만 포함되어 있으면 수행 중인 작업이 올바른 것입니다.
sed "$lnum!d" cloud.cpp
sed
일반적으로 쉘 변수를 전달 하려면 다음을 읽으십시오.이 답변.
이제 이 경우 올바르게 수행했지만 여전히 작동하지 않습니다. 이는 셸 때문일 bash
수 zsh
있습니다 csh
. 이러한 셸은 !
(이 기능은 원래 에서 제공되었으며 csh
나중에 복사됨 bash
) 로 표시되는 역사적 확장을 지원합니다 zsh
.
에서는 대화형 세션에서 기록 확장 bash
이 zsh
기본적으로 활성화되며 큰따옴표 안에 수행됩니다.
존재하다 zsh
:
$ seq 10 | sed "10!d" # <-- press enter
$ seq 10 | sed "10dash"
이것은 dash
내 역사상 으로 시작하는 가장 최근의 명령입니다 d
.
존재하다 bash
:
$ seq 10 | sed "10!d"
bash: !d": event not found
.bash로 시작하는 bash 기록에는 아무것도 없기 때문입니다 d
.
기록 확장을 끌 수 있습니다.
set +H
또는:
set +o histexpand
함께 하다 bash
:
set -K
또는:
setopt nohistexpand
존재하다 zsh
.
보다 이식 가능한 방법을 위해 쉘 옵션에 의존하지 않고 언제든지 다음을 수행할 수 있습니다.
sed "$lnum"\!d cloud.cpp
이렇게 하면 쉘이 !
문자 그대로 처리됩니다.
답변2
언급한 대로 문자열에 작은따옴표를 사용하면 해당 내용이 문자 그대로 처리되므로 큰따옴표를 사용해야 합니다. 그러나 귀하의 경우에는 패턴과 변수의 조합이 있습니다. 따라서 패턴에는 작은따옴표를, 변수에는 큰따옴표를 사용해야 합니다.
sed "$lnum"'!d' cloud.cpp
답변3
어떤 쉘을 사용하고 있는지 언급하지 않았습니다. 아래 답변은 다음과 같다고 가정합니다 bash
.
셸에서 기록 확장을 트리거하고 있습니다. 에서 man bash
:
!string
문자열로 시작하는 기록 목록에서 현재 위치 이전의 가장 최근 명령을 참조합니다.
이상한 점은 다음과 같습니다.
!
활성화되면 큰따옴표 안에 표시되는 내용이 백슬래시를 사용하여 이스케이프되지 않는 한 기록 확장이 수행됩니다 . 앞의 백슬래시는!
제거되지 않습니다.
그래서 나는 그것들을 개별적으로 인용하는 것이 아마도 가장 좋은 해결책이라고 생각합니다.
sed "$lnum"'!d' cloud.cpp
이것은 또한 작동합니다(캐릭터를 저장합니다):
sed "$lnum"\!d cloud.cpp
이것은 또한 작동합니다(큰따옴표를 선호하는 경우):
sed "$lnum""!""d" cloud.cpp