답변:
이식 가능하게 하나 이상의 인수를 한 #!
줄 에 넣을 수는 없습니다 . 이는 전체 경로와 하나의 인수 (예 : #!/bin/sed -f
또는 #!/usr/bin/sed -f
) 또는 #!/usr/bin/env
통역사에 대한 인수가 없음을 의미합니다.
이식 가능한 스크립트를 얻는 해결 방법 #!/bin/sh
은 sed 스크립트를 명령 줄 인수로 전달하여 쉘 래퍼 를 사용 하는 것입니다. 이것은 POSIX에 의해 제재되지 않았으며 (다중 명령어 스크립트는 -e
이식성을 위해 각 명령어마다 별도의 인수 로 작성되어야 함 ), 많은 구현에서 작동합니다.
#!/bin/sh
exec sed '
s/a/b/
' "$@"
긴 스크립트의 경우 heredoc을 사용하는 것이 더 편리 할 수 있습니다. heredoc의 장점은 안에 작은 따옴표를 인용 할 필요가 없다는 것입니다. 주요 단점은 스크립트가 표준 입력에 sed로 공급되고 두 가지 성가신 결과가 발생한다는 것입니다. sed의 일부 버전 -f /dev/stdin
대신을 -f -
(를) 필요로하므로 이식성에 문제가 있습니다. 게다가 표준 입력은 스크립트이고 데이터가 될 수 없기 때문에 스크립트는 필터로 작동 할 수 없습니다.
#!/bin/sh
exec sed -f - -- "$@" <<'EOF'
s/a/b/
EOF
heredoc의 단점은의 유용한 사용법으로 해결할 수 있습니다 cat
. 이렇게하면 전체 스크립트가 명령 줄에 다시 표시되므로 POSIX 호환이 아니라 실제로 이식성이 뛰어납니다.
#!/bin/sh
exec sed "$(cat <<'EOF')" -- "$@"
s/a/b/
EOF
또 다른 해결 방법은 sh와 sed로 구문 분석 할 수있는 스크립트를 작성하는 것입니다. 이것은 휴대용이며 합리적으로 효율적이며 조금 추악합니다.
#! /bin/sh
b ()
{
x
}
i\
f true; then exec sed -f "$0" "$@"; fi
: ()
# sed script starts here
s/a/b/
설명 :
b
. 함수가 구문 적으로 잘 구성된 한 내용은 중요하지 않습니다 (특히 빈 함수를 가질 수 없음). 그런 다음 참이면 (즉, 항상) sed
스크립트 에서 실행 하십시오.()
레이블로 분기 한 다음 올바른 형식의 입력. 그런 다음 i
명령은 항상 건너 뛰기 때문에 효과가 없습니다. 마지막으로 ()
레이블 뒤에 스크립트의 유용한 부분이 있습니다.#!/usr/bin/env
논쟁이 없다." 잘 표현되지 않았습니다. 아마도 "또는 #!/usr/bin/env sed
sed에 대한 논쟁이 없습니다."
GNU coreutils v8.30 부터 다음을 수행 할 수 있습니다.
#!/usr/bin/env -S sed -f
이 기능은 GNU coreutils 패키지에 최근 (2018-04-20) 커밋 에 env.c
추가되었으며 -S
or --split-string
옵션 이 추가되었습니다 .
로부터 env
매뉴얼 페이지
OPTIONS
-S/--split-string usage in scripts
The -S option allows specifing multiple parameters in a script.
Running a script named 1.pl containing the following first line:
#!/usr/bin/env -S perl -w -T
Will execute perl -w -T 1.pl .
Without the '-S' parameter the script will likely fail with:
/usr/bin/env: 'perl -w -T': No such file or directory
See the full documentation for more details.
더 많은 예제는 GNU coreutils 매뉴얼에 있습니다 .
-v
자세한 출력 옵션을 사용하는 경우 env
인수 문자열이 어떻게 분리 되는지 정확히 알 수 있습니다
.
에서 my_sed_script.sed
:
#!/usr/bin/env -vS sed -f
s/a/b/
실행:
$ ./my_sed_script.sed
split -S: ‘sed -f’
into: ‘sed’
& ‘-f’
executing: sed
arg[0]= ‘sed’
arg[1]= ‘-f’
arg[2]= ‘./my_sed_script.sed’
참고 : 이 경우에만 사용 shebangs 적용 /usr/bin/env
으로,
--split-string
GNU의 기능입니다 env
특히.
이 답변은 우아한 솔루션에 대한 경로를 제공합니다 : /programming//a/1655389/642372
read
쉘 변수에 heredoc.sed
.견본:
#!/usr/bin/env bash
read -rd '' SED_SCRIPT <<EOD
# Your sed script goes here.
s/a/b/
EOD
exec sed "$SED_SCRIPT" "$@"
나는 Walker의 솔루션을 좋아하지만 개선 될 수 있습니다 (댓글은 미리 형식이 지정된 텍스트를 허용하지 않기 때문에 별도의 답변으로 작성). 모든 Linux 또는 Bash 버전에서는 작동하지 않을 수 있지만 Ubuntu 17.10에서는 다음과 같이 줄일 수 있습니다.
#!/usr/bin/env bash
read SED_SCRIPT <<EOD
s/a/b/
EOD
sed "$SED_SCRIPT" "$@"
명령을 제거하고 명령을 eval
단순화 할 수 read
있지만 heredoc 내에서 주석을 제거해야합니다.
또한 sed에 대해 알고 싶었지만 묻기를 두려워하는 모든 것에 대해 http://www.grymoire.com/unix/sed.html에 매우 유용한 자습서가 있습니다. 이것은 /usr/bin/env
sed에 대한 경로를 잃고 하드 코딩하는 비용을 들이지 않고 더 나은 솔루션을 제안합니다 .
#!/bin/sed -f
s/a/b/
s/c/d/
이는 둘 이상의 s///
교체 를 지원한다는 추가 이점이 있습니다 .