Bash 스크립트와 대화형 셸 간의 공백 차이

Bash 스크립트와 대화형 셸 간의 공백 차이

왜 이런 일이 발생하는지 알려주세요.

Linux bash 셸에서:

ps
PID TTY          TIME CMD
20406 pts/0    00:00:01 bash
26896 pts/0    00:00:00 ps

다음 명령을 실행합니다.

str="a b c d"
printf "%s\n"  ` echo $str `
a
b
c
d

하지만 bash 스크립트에서

#!/bin/bash
.
.
.
.

str="a b c d"
printf "%s\n"  ` echo $str `

다음과 같이 인쇄됩니다.

a b c d  

그리고 스크립트의 예상 결과는 다음과 같아야 합니다.

a
b
c
d

내 Bash 스크립트에서 무엇을 놓치고 있나요? bash ENV나 이와 유사한 것일 수도 있습니다.

또한 shoptbash 스크립트에서 명령을 실행했는데 결과는 다음과 같습니다.

  utocd  off
  cdable_vars  off
  cdspell  off
  checkhash  off
  checkjobs  off
  checkwinsize  off
  cmdhist  on
  compat31  off
  compat32  off
  compat40  off
  compat41  off
  direxpand  off
  dirspell  off
  dotglob  off
  execfail  off
  expand_aliases  off
  extdebug  off
  extglob  off
  extquote  on
  failglob  off
  force_fignore  on
  globstar  off
  gnu_errfmt  off
  histappend  off
  histreedit  off
  histverify  off
  hostcomplete  on
  huponexit  off
  interactive_comments  on
  lastpipe  off
  lithist  off
  login_shell  off
  mailwarn  off
  no_empty_cmd_completion  off
  nocaseglob  off
  nocasematch  off
  nullglob  off
  progcomp  on
  promptvars  on
  restricted_shell  off
  shift_verbose  off
  sourcepath  on
  xpg_echo  off

답변1

이 동작은 두 가지 상황에서만 재현할 수 있습니다.

  1. 큰따옴표 명령 대체:

    #!/bin/bash
    
    str="a b c d"
    printf "%s\n"  "`echo $str`"
    
  2. 또는 내부 필드 구분 기호( IFS변수)를 변경합니다. 예를 들면 다음과 같습니다.

    #!/bin/bash
    
    IFS=,
    str="a b c d"
    printf "%s\n" `echo $str`
    

두 경우 모두 출력은 다음과 같습니다.

$ ./test.sh
a b c d

첫 번째 경우를 수정하려면 따옴표를 제거하고 복원하려면 IFS명령 대체 위의 기본값으로 설정하면 됩니다.

IFS=$' \t\n'

IFS변경 후 출력이 달라지는 이유와 큰따옴표의 공통점이 무엇인지 조금 설명해주세요 .

끝부터 시작해 보겠습니다.

printf "%s\n" a b c d

와는 크게 다르다

printf "%s\n" 'a b c d'

첫 번째 경우에는 4개의 개별 단어가 있고 printf이를 하나씩 출력하여 새 줄을 추가합니다. 두 번째 경우에는 전체 단어가 a b c d단일 단어로 처리되어 printf터미널에 직접 출력됩니다. 이제 큰따옴표를 추가하면 의 출력이 `echo $str`단일 단어로 처리된다는 것이 분명해졌습니다.

이제 IFS그것이 시작되는 곳입니다. 즉, 확장 후 단어를 분할하는 데 tt가 사용되므로 기본적으로 IFS=$' \t\n'표현식은 echo a b c d출력이지만 a b c d명시 적인 따옴표를 사용하지 않아도 - 세계가 IFS=,됩니다 . 'a b c d'변수 없이 이를 더 명확하게 확인할 수 있습니다.

$ IFS=,
$ printf "%s\n"  `echo a b c d`
a b c d

$ IFS=$' \t\n'
$ printf "%s\n"  `echo a b c d`
a
b
c
d

$()마지막 참고 사항: 백틱 대신 명령 대체 형식을 사용하는 것이 더 좋지만 이는 다른 주제입니다.

관련 정보