2017-09-20 1 views
0

나는 아주 잘 bash는 스크립트를 이해할 수 있다고 생각하는 데 사용하지만, 뭔가가 최근 문제에 대한 이해를 요구했다 : bash에서 단어 분리가 언제 발생합니까?

나는 공백으로 IFS의 값에 아무것도를 교체 한 후 그 단어 분할 분할 스캐닝 입력하여 작품을 생각했다.

나는 나의 IFS를 인쇄하고 그것이 그냥 공간으로 모든 탭, 개행 문자 및 공백을 변환해야 하더군요

>>> echo “$IFS” | xxd 
00000000: 2009 0a0a 

입니다.

그래서,이 테스트를하기로 결정했다 : 나는 \s\n 변환 것이라고 기대

list_of_stuff=("\n") 

for elm in "${list_of_stuff[@]}" 
do 
    echo $elm 
done 

.

>>> sh test_bash_script.sh 


>>> 

내가 기대하는대로 \s\n 변환되지 않는다는 것을 알려줍니다 요식 :하지만, 내가 실행할 때이 다음과 같은 출력을 얻을. 이 전환이 언제 발생해야합니까?

답변

2

배열에 줄 바꿈이 없으며 백 슬래시 문자 뒤에 "n"이옵니다. 셸에서 echo $elm을 실행하면 $elm을 '\ n'으로 변환하고 단어 분할 (공백 문자가 없음)을 수행 한 다음이를 인수로 echo으로 전달합니다. echo\n을보고, 그것을 개행 문자로 변환하고이를 인쇄하는 이스케이프 해석을 수행합니다 (일부 버전은 echo, 일부는 수행하지 않음).

`printf와 함께 그것을 시도 " '% s'을 (를) \ n"무슨 일이 일어나고 있는지 더 나은 아이디어를 얻을 $ 느릅 나무 :

$ list_of_stuff=("\n") 
$ for elm in "${list_of_stuff[@]}"; do 
> printf "'%s'\n" $elm 
> done 
'\n' 
$ list2=($'\n') # This'll give an actual newline 
$ for elm in "${list2[@]}"; do 
> printf "'%s'\n" $elm 
> done 
'' 

하지만 ...이 왜 그 두 번째 아무것도 인쇄하지 않았다을? $elm이 줄 바꿈으로 확장 되었기 때문에 단어 분할이 0 단어가되어 printf "'%s'\n"에 해당하는 줄을 실행 했으므로 줄 바꿈 뒤에 두 개의 작은 따옴표가 인쇄됩니다.

현재로서는 set -x을 사용하여 이와 같은 경우에 어떤 일이 벌어 졌는지 더 잘 알 수 있습니다. 원래의 경우에는 echo '\n'을 실행 중임을 나타냅니다.

[편집] 0 단어로 바뀌었고 printf "'%s'\n"에 해당하는 질문에 대답하려면 단어 분리가 공백으로 바뀌지 않습니다. 문자열을 일련의 단어로 변환합니다. echo이 여러 개의 인수 ("단어")를 얻는 경우 공백과 함께 공백을 넣으므로 단어 분리 + echo은 모든 공백을 단일 공백으로 바꾸는 효과를 가질 수 있지만 실제로는 어떤 단어 분할 자체가 아닌 것입니다. 몇 가지 예를 고려해

$ var1=$' \t word1 \n \t word2 \nword3 \n \n ' # Note that $' ' converts escape sequences 
$ printf "'%s'\n" "$var1" # This prints the actual contents with quotes around, no further interpretation 
' word1 
     word2 
word3 


' 
$ echo $var1 # No quotes, so it gets word-split; echo pastes together with spaces 
word1 word2 word3 
$ printargs() { # Let's define a function to show what's happening more clearly 
> echo "Received $# arguments:" 
> for arg in "[email protected]"; do 
> printf " '%s'\n" "$arg" 
> done 
> } 
$ printargs $var1 
Received 3 arguments: 
    'word1' 
    'word2' 
    'word3' 

이의 좀 더 자세히 echoprintargs 명령을 살펴 보자. echo $var1에서 값 $var1은 공백 (공백, 탭 및 줄 바꿈)에서 단어 분할을 가져 와서 단어 "word1", "word2"및 "word3"의 세 단어로 바꿉니다. 여기에는 공백이 없으며 모두 제거되었습니다. 따라서 echo "word1" "word2" "word3"과 동일한 코드를 실행하고 echo은 3 개의 인수를 취하고 그 사이에 공백을 추가 한 다음 결과를 인쇄합니다.

이제 인자 수를 출력하고 각 인자 (들여 쓰기 및 작은 따옴표)를 출력하는 함수로 printargs을 정의했습니다. 따라서 printargs $var1에서 단어 분리는 동일하게 발생하므로 printargs "word1" "word2" "word3"과 동일한 코드를 실행하므로 printargs은 세 개의 인수가 있다고보고하고 각 인수를 따로 따로 인쇄합니다 (들여 쓰기를 위해 공백을 추가하지 않은 공백은 제외). 예

좋아, 다음 시리즈 : 다시

$ var2=$' \t \t \n \t ' # All whitespace this time 
$ printf "'%s'\n" "$var2" 
'   
     ' 
$ echo $var2 

$ printargs $var2 
Received 0 arguments: 

은, 더 자세히 마지막 두 명령을 살펴 보자 : echo $var2에서이 단어 분할은 $var의 값에 영 단어를 발견 - 모든 공백입니다 그래서 035를 echo에 전달합니다. 명령은 인수가 전혀없는 echo과 동일합니다. 따라서 echo은 빈 줄만 인쇄합니다 (공백이나 아무것도 사용하지 않음). 마찬가지로 printf "'%s'\n" $var2에서 $var2 단어가 0 단어로 나뉘므로 printargs은 0 개의 인수를 가져오고보고합니다. 출력을 다음과 같은 완전히 동일한 명령으로 비교하십시오.

$ echo 

$ printargs 
Received 0 arguments: 
+0

감사합니다. 나는 너의 설명에 약간 혼란 스럽다. 당신이 "어떤 단어 분리가 0 단어로 바뀌 었습니다 ..."라고 말할 때, 그것이 바로 공간으로 바뀌 었음을 의미합니까? 왜냐하면 그것은'IFS'에 대한 디폴트 값을 사용하는 단어 분할 방식 때문입니다. – guimption

+0

또한, 나는 그것이 "printf" '% s'\ n "'"와 같은 의미인지 이해하지 못합니다. 그것들은 어떻게 비슷합니까? 감사합니다. – guimption

+1

@guimption : 아니오, 단어 분리는 아무 것도 공간으로 변환하지 않습니다. 내 편집을 참조하십시오. –

관련 문제