분할 시 파일에서 IFS 값이 제거되는 이유는 무엇입니까?

분할 시 파일에서 IFS 값이 제거되는 이유는 무엇입니까?
IFS=$'?\n'
for line in $(cat "./newfiletoread")
do printf "${line}\n"
done

파일 내용은 다음과 같습니다. 안녕하세요! 괜찮으세요? 인생은 어때요? 내 인생은 겨울 아침만큼 지루합니다!

위의 코드는 '?' 또는 '!'를 발견하면 파일의 내용을 분할합니다. ' 또는 '/n'이면 괜찮습니다. 그러나 확장 중에 쉘은 파일에서 이러한 문자를 제거합니다. 아래는 내가 얻은 결과입니다.

Hello there 
How are you doing
How is life
Mine is as boring as a winter morning

명령이 실행되기 전에 이러한 IFS 값을 공백으로 바꾸면 쉘이 작동한다는 것을 알고 있습니다. 분할하는 동안 이러한 구분 기호를 유지하는 방법이 있습니까? 아래와 같은 출력을 얻고 싶습니다.

Hello there! 
How are you doing?
How is life?
Mine is as boring as a winter morning!

답변1

첫 번째,파일에서 줄을 읽지 마세요for

문자열 분할에 대해 어딘가에서 읽었습니다. split무엇을 버려야 할지 알 때 사용하고, 무엇을 유지해야 할지 알 때 정규식을 사용하십시오. 또는 그런 것.

쉘 단어 분할을 사용할 때의 문제점 $IFS은 해당 변수의 모든 문자가 분할에 사용되며 어느 문자인지 알 수 없다는 것입니다.

Bash를 사용하면 다음과 같이 작성할 수 있습니다.

line='Hello there! How are you doing? How is life? Mine is as boring as a winter morning!'
line=${line//\?/$'"?\n'}
line=${line//\!/$'"!\n'}
echo "$line"
Hello there"!
 How are you doing"?
 How is life"?
 Mine is as boring as a winter morning"!

선행 공백에 유의하십시오. 이는 보다 복잡한 패턴으로 해결할 수 있습니다.line=${line//\?*([[:blank:]])/$'"?\n'}

나는 다음을 사용할 것이다 sed:

line='Hello there! How are you doing? How is life? Mine is as boring as a winter morning!'
new=$( sed 's/[?!][[:blank:]]*/&\n/g' <<<"$line" )
echo "$new"
Hello there! 
How are you doing? 
How is life? 
Mine is as boring as a winter morning!

split()구분 기호를 캡처할 수 있는 기능이 있지만 이를 사용하는 것은 매우 장황합니다.

echo "$line" | awk '{
    n = split($0, words, /[!?][[:blank:]]*/, seps)
    for (i = 1; i < n; i++) 
        print words[i] seps[i]
    print words[n]}
'

관련 정보