얼마 전에 파일에서 입력을 읽는 코드를 찾았는데, Stack Exchange를 통해 내 필요에 맞게 조정할 수 있었다고 생각합니다.
while read -r line || [[ -n "$line" ]]; do
if [[ $line != "" ]]
then
((x++))
echo "$x: $line"
# <then do something with $line>
fi
done < "$1"
지금 내 스크립트를 검토하고 그것이 무엇을 하는지 이해하려고 노력하고 있습니다. 이 명령문이 무엇을 하는지 이해가 되지 않습니다.
while read -r line || [[ -n "$line" ]];
나는 그 -r
옵션이 우리가 원시 텍스트를 읽는다는 것을 의미한다는 것을 알고 있지만 $line
진술의 해당 부분에 대해 혼란스럽습니다. || [[ -n "$line" ]]
누군가 이것이 무엇을 하는지 설명할 수 있습니까?
답변1
[[ -n "$line" ]]
$line
(방금 읽은 변수 )가 비어 있지 않은지 테스트합니다 read
. read
다음과 같은 경우 성공을 반환하므로 유용합니다 .~하지 않는 한그것은 본다개행 문자파일이 끝나기 전에. 입력에 끝에 개행 문자가 없는 줄 조각이 포함되어 있는 경우 이 테스트는 해당 줄을 캡처하고 루프는 최종 불완전한 줄도 처리합니다. 추가 테스트 없이는 불완전한 줄을 읽을 수 있지만 $line
루프에서는 무시됩니다.
POSIX가 정의하기 때문에 "불완전한 줄"이라고 말합니다.텍스트 파일그리고한 줄각 줄 끝에 개행 문자가 필요합니다. 다른 도구 read
도 관리할 수 있습니다.wc -l
개행 문자 수를 계산합니다., 따라서 마지막 불완전한 줄은 무시됩니다. 예를 들어 참조하십시오.파일 끝에 새 줄을 추가하는 이유는 무엇입니까?그리고텍스트 파일이 줄바꿈으로 끝나야 하는 이유는 무엇입니까?그게 다야.
물론 이 cmd1 || cmd2
구조는 C의 동등한 구조와 유사합니다. 첫 번째 명령이 오류 상태를 반환하면 두 번째 명령이 실행되고 결과는 실행된 마지막 명령의 종료 상태입니다.
비교하다:
$ printf 'foo\nbar' | ( while read line; do
echo "in loop: $line"
done
echo "finally: $line"
)
in loop: foo
finally: bar
그리고
$ printf 'foo\nbar' | ( while read line || [[ -n $line ]]; do
echo "in loop: $line"
done
echo "finally: $line"
)
in loop: foo
in loop: bar
finally:
답변2
이건 좀 혼란스럽다왜거기에 있지만 그것이 무엇을 하는지 설명하는 것은 간단합니다. 길이가 0이 아닌 한 true(성공)를 반환하는 ||
OR 문입니다 . 여기서 혼란스러워집니다. 성공(0) 종료 상태가 있을 때 while 루프가 계속 실행됩니다. 줄이 비어 있더라도 파일 끝에 도달할 때까지 줄을 계속 읽고 0 종료 상태를 반환합니다. 0이 아닌 종료 코드가 반환되는 경우에만 실행되며 , 이 경우 비어 있습니다. 테스트는 다음과 같은 경우 true를 반환 하므로[[ -n
"$line"
read
[[ -n "$line" ]]
read
$line
$line
아니요비어 있으면 0이 아닌 출구로 돌아가 루프에서 빠져 나옵니다 while
.내가 아는 한 (@ilkkachu가 지적했듯이, 이것은 후행 개행 문자가 누락된 입력의 홀수 마지막 줄을 포착합니다. 이러한 파일은 유효한 텍스트 파일이 아닙니다.유효한 행이 아닙니다.)|| [[ -n "$line" ]]
실제로 성취된 것은 아무것도 없다.
무엇예가끔씩 작동한다면 그냥 하십시오 while read -r line && [[ -n "$line" ]]
. (AND)를 사용하면 행을 읽을 수 있고 행이 비어 있지 않은 경우 &&
전체 문이 0 상태만 반환한다는 의미입니다. 첫 번째 빈 줄에서 루프가 중지 read
됩니다 . while
추측하자면 이 코드는가능한이 작업을 수행한 것에서 수정되었습니다. 단순히 테스트를 제거하는 대신 작성자는 &&
이를 ||
.