program tip

shebang과 함께 awk에 여러 인수를 사용하는 방법 (예 : #!)?

radiobox 2020. 7. 25. 10:45
반응형

shebang과 함께 awk에 여러 인수를 사용하는 방법 (예 : #!)?


shebang 사용하여 gawk 스크립트 를 실행하고 싶습니다 --re-interval. "순진한"접근 방식

#!/usr/bin/gawk --re-interval -f
... awk script goes here

gawk가 "--re-interval -f"이해하지 못하는 첫 번째 인수 (공백으로 나뉘 지 않음 )로 호출되기 때문에 작동 하지 않습니다. 이에 대한 해결 방법이 있습니까?

물론 gawk를 직접 호출 할 수는 없지만 첫 번째 인수를 분할하는 쉘 스크립트로 랩핑하거나 gawk를 호출하여 스크립트를 다른 파일에 넣는 쉘 스크립트를 만들 수는 있지만 방법이 있는지 궁금합니다. 하나의 파일 내에서.

Shebang 행의 동작은 시스템마다 다릅니다. 적어도 Cygwin 에서는 인수를 공백으로 나누지 않습니다. 나는 그런 행동을하는 시스템에서 어떻게해야하는지에 관심이있다. 스크립트는 이식성이 없어야합니다.


이것은 (g) awk와 함께 작동하는 것 같습니다.

#!/bin/sh
arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"


# The real awk program starts here
{ print $0 }

#!runs을 참고 /bin/sh하여이 스크립트는 먼저 쉘 스크립트로 해석됩니다.

처음에는 간단히 시도 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"했지만 awk는 명령으로 처리하고 모든 입력 줄을 무조건 인쇄했습니다. 그것이 내가 넣은 이유입니다 arbitrary_long_name==0-항상 실패해야합니다. 횡설수설로 바꿀 수 있습니다. 기본적으로 쉘 스크립트에 부정적인 영향을 미치지 않는 잘못된 조건을 찾고있었습니다.

쉘 스크립트 arbitrary_long_name==0에서는이라는 변수를 정의하고 변수를 arbitrary_long_name동일하게 설정합니다 =0.


shebang 라인은 POSIX, SUS, LSB 또는 기타 사양의 일부로 지정되지 않았습니다. AFAIK, 제대로 문서화되지 않았습니다.

사이 모든 것을 가지고 : 그것은 무엇을하는지에 대한 대략적인 합의가 !\nexec그것. !사이의 모든 것이 \n통역사에게 완전한 절대 경로 라고 가정 합니다. 공백이 있으면 어떻게되는지에 대한 합의가 없습니다.

  1. 일부 운영 체제는 단순히 전체를 경로로 취급합니다. 결국, 대부분의 운영 체제에서 공백이나 대시는 경로에서 합법적입니다.
  2. 일부 운영 체제는 공백으로 분할되어 첫 번째 부분은 인터프리터의 경로로, 나머지는 개별 인수로 취급합니다.
  3. 일부 운영 체제는 첫 번째 공백 에서 분할되고 앞 부분을 인터 페터로의 경로로 취급하고 나머지는 하나의 인수 (현재보고있는 것)로 취급합니다.
  4. 일부는 심지어 shebang 라인 을 전혀 지원하지 않습니다 .

고맙게도, 1.과 4.는 사망 한 것으로 보이지만 3.은 매우 널리 퍼져 있으므로 단순히 하나 이상의 인수를 전달할 수는 없습니다.

명령의 위치도 POSIX 또는 SUS에 지정되지 않기 때문에, 당신은 일반적으로 실행 파일의 전달하여 하나의 인자 것을까지 사용할 이름env수 있도록 그것을 실행 파일의 위치를 확인할 수 있습니다; 예 :

#!/usr/bin/env gawk

[분명히, 이것은 여전히 특정 경로를 가정 env하지만 시스템이 존재하는 시스템은 거의 /bin없기 때문에 일반적으로 안전합니다. 의 위치는 env훨씬 더의 위치보다 표준화 gawk와 같은 또는 더 나쁜 일 python또는 rubyspidermonkey.]

이것은 실제로 어떤 인수도 사용할 수 없다는 것을 의미 합니다 .


공백을 처리하는 방식 (적어도 Linux에서는)으로 인해 명확한 해결책이없는 동일한 문제가 발생했습니다.

그러나 짧은 옵션 이고 연결할 수있는 한 (GNU 방식) 세방에서 여러 옵션을 전달할 수 있습니다 .

예를 들어, 당신은 가질 수 없습니다

#!/usr/bin/foo -i -f

하지만 당신은 가질 수 있습니다

#!/usr/bin/foo -if

옵션이 짧고 인수가없는 경우에만 작동합니다.


Cygwin 및 Linux에서는 shebang 경로 이후의 모든 것이 하나의 인수로 프로그램에 구문 분석됩니다.

awkshebang 내부에서 다른 스크립트 를 사용하여이 문제를 해결할 수 있습니다.

#!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}

이것은 {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}awk에서 실행 됩니다.
그리고 이것은 /usr/bin/gawk --re-interval -f path/to/your/script.awk시스템 쉘에서 실행될 것 입니다.


Although not exactly portable, starting with coreutils 8.30 and according to its documentation you will be able to use:

#!/usr/bin/env -S command arg1 arg2 ...

So given:

$ cat test.sh
#!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too

you will get:

% ./test.sh 
$0 is '/usr/local/bin/showargs'
$1 is 'here'
$2 is 'is another'
$3 is 'long'
$4 is 'arg'
$5 is '-e'
$6 is 'this and that '
$7 is 'too'
$8 is './test.sh'

and in case you are curious showargs is:

#!/usr/bin/env sh
echo "\$0 is '$0'"

i=1
for arg in "$@"; do
    echo "\$$i is '$arg'"
    i=$((i+1))
done

Original answer here.


#!/bin/sh
''':'
exec YourProg -some_options "$0" "$@"
'''

The above shell shebang trick is more portable than /usr/bin/env.


In the gawk manual (http://www.gnu.org/manual/gawk/gawk.html), the end of section 1.14 note that you should only use a single argument when running gawk from a shebang line. It says that the OS will treat everything after the path to gawk as a single argument. Perhaps there is another way to specify the --re-interval option? Perhaps your script can reference your shell in the shebang line, run gawk as a command, and include the text of your script as a "here document".


Why not use bash and gawk itself, to skip past shebang, read the script, and pass it as a file to a second instance of gawk [--with-whatever-number-of-params-you-need]?

#!/bin/bash
gawk --re-interval -f <(gawk 'NR>3' $0 )
exit
{
  print "Program body goes here"
  print $1
}

(-the same could naturally also be accomplished with e.g. sed or tail, but I think there's some kind of beauty depending only on bash and gawk itself;)


Just for fun: there is the following quite weird solution that reroutes stdin and the program through file descriptors 3 and 4. You could also create a temporary file for the script.

#!/bin/bash
exec 3>&0
exec <<-EOF 4>&0
BEGIN {print "HALLO"}
{print \$1}
EOF
gawk --re-interval -f <(cat 0>&4) 0>&3

One thing is annoying about this: the shell does variable expansion on the script, so you have to quote every $ (as done in the second line of the script) and probably more than that.


For a portable solution, use awk rather than gawk, invoke the standard BOURNE shell (/bin/sh) with your shebang, and invoke awk directly, passing the program on the command line as a here document rather than via stdin:

#!/bin/sh
gawk --re-interval <<<EOF
PROGRAM HERE
EOF

Note: no -f argument to awk. That leaves stdin available for awk to read input from. Assuming you have gawk installed and on your PATH, that achieves everything I think you were trying to do with your original example (assuming you wanted the file content to be the awk script and not the input, which I think your shebang approach would have treated it as).

참고URL : https://stackoverflow.com/questions/4303128/how-to-use-multiple-arguments-for-awk-with-a-shebang-i-e

반응형