다음 .txt 파일이 있습니다.
Marco
Paolo
Antonio
한 줄씩 읽고 싶습니다. 각 줄마다 .txt 줄 값을 변수에 할당하고 싶습니다. 내 변수가이라고 가정하면 $name
흐름은 다음과 같습니다.
- 파일에서 첫 번째 줄 읽기
- 할당
$name
= "마르코" - 몇 가지 작업을 수행
$name
- 파일에서 두 번째 줄 읽기
- Assign
$name
= "Paolo"
다음 .txt 파일이 있습니다.
Marco
Paolo
Antonio
한 줄씩 읽고 싶습니다. 각 줄마다 .txt 줄 값을 변수에 할당하고 싶습니다. 내 변수가이라고 가정하면 $name
흐름은 다음과 같습니다.
$name
= "마르코"$name
$name
= "Paolo"답변:
다음은 한 줄씩 인수로 전달 된 파일을 읽습니다.
while IFS= read -r line; do
echo "Text read from file: $line"
done < my_filename.txt
이것은 루프에서 파일에서 행을 읽는 표준 형식 입니다. 설명:
IFS=
(또는 IFS=''
) 선행 / 후행 공백이 잘리지 않도록합니다.-r
백 슬래시 이스케이프가 해석되지 않도록합니다.또는 bash 파일 도우미 스크립트 (예제 내용)에 넣을 수 있습니다.
#!/bin/bash
while IFS= read -r line; do
echo "Text read from file: $line"
done < "$1"
위의 파일 이름이 filename으로 스크립트에 저장 readfile
되면 다음과 같이 실행할 수 있습니다.
chmod +x readfile
./readfile filename.txt
파일이 표준 POSIX 텍스트 파일이 아닌 경우 (= 개행 문자로 끝나지 않음) 후행 부분 행을 처리하도록 루프를 수정할 수 있습니다.
while IFS= read -r line || [[ -n "$line" ]]; do
echo "Text read from file: $line"
done < "$1"
여기 || [[ -n $line ]]
에서 마지막 줄이 E로 끝나지 않으면 0이 아닌 종료 코드를 반환 \n
하므로 끝으로 무시되지 않도록 read
합니다.
루프 내부의 명령이 표준 입력에서도 읽히는 경우에 사용되는 파일 디스크립터 read
는 다른 표준 파일 디스크립터를 피할 수 있습니다 . 예를 들면 다음과 같습니다.
while IFS= read -r -u3 line; do
echo "Text read from file: $line"
done 3< "$1"
비 Bash 쉘은 알지 못할 수도 read -u3
있으므로 read <&3
대신 사용하십시오.
ssh
없으면 -n
효과적으로 루프를 벗어날 수 있습니다. 아마도 이것에 대한 좋은 이유가 있지만 이것을 발견하기 전에 코드가 실패하는 원인을 알아내는 데 시간이 걸렸습니다.
ffmpeg
stdin 을 소비 하여 발생합니다 . 추가 </dev/null
사용자에 ffmpeg
라인이 수에, 또는 루프에 대한 대체 FD를 사용하지 않습니다. "대체 FD"접근 방식은 다음과 같습니다 while IFS='' read -r line <&3 || [[ -n "$line" ]]; do ...; done 3<"$1"
.
.sh
확장 권고 . UNIX의 실행 파일에는 일반적으로 확장 기능이 전혀 없으며 (실행하지 않음 ls.elf
) bash shebang (및 같은 bash 전용 툴링 [[ ]]
) 및 POSIX sh 호환성을 암시하는 확장 기능은 내부적으로 모순됩니다.
다음을 나타내는 -r
플래그 를 사용하는 것이 좋습니다 read
.
-r Do not treat a backslash character in any special way. Consider each
backslash to be part of the input line.
에서 인용하고 man 1 read
있습니다.
또 다른 것은 파일 이름을 인수로 취하는 것입니다.
업데이트 된 코드는 다음과 같습니다.
#!/usr/bin/bash
filename="$1"
while read -r line; do
name="$line"
echo "Name read from file - $name"
done < "$filename"
sh
아닌 것 같습니다 bash
. || [[ -n "$line" ]]
허용되는 답변 의 구문에 사용 된 확장 테스트 명령 은 bashism입니다. 즉,이 구문은 실제로 의미가 있습니다. 줄 바꿈이 없어도 입력 파일의 마지막 줄에 대해 루프가 계속됩니다. POSIX 호환 방식으로 원한다면 || [ -n "$line" ]
을 사용 하고 싶을 [
것 [[
입니다.
IFS=
에 대한 read
공백을 트리밍 방지 할 수 있습니다.
다음 Bash 템플릿을 사용하면 파일에서 한 번에 하나의 값을 읽고 처리 할 수 있습니다.
while read name; do
# Do what you want to $name
done < filename
*
.
#! /bin/bash
cat filename | while read LINE; do
echo $LINE
done
Enter
, 마지막 줄 다음 에 눌러야 함 ). 그렇지 않으면 마지막 줄이 무시됩니다. 적어도 그것이 저에게 일어난 일입니다.
많은 사람들이 과도하게 최적화 된 솔루션을 게시했습니다. 나는 그것이 틀렸다고 생각하지 않지만 겸손하게 모든 사람들 이이 작동 방식을 쉽게 이해할 수 있도록 덜 최적화 된 솔루션이 바람직하다고 생각합니다. 내 제안은 다음과 같습니다.
#!/bin/bash
#
# This program reads lines from a file.
#
end_of_file=0
while [[ $end_of_file == 0 ]]; do
read -r line
# the last exit status is the
# flag of the end of file
end_of_file=$?
echo $line
done < "$1"
사용하다:
filename=$1
IFS=$'\n'
for next in `cat $filename`; do
echo "$next read from $filename"
done
exit 0
IFS
다르게 설정 하면 이상한 결과가 나타납니다.
*
한 줄에 단일 파일이 들어있는 파일로 시도 했 습니까? 어쨌든 이것은 반 패턴 입니다. for로 줄을 읽지 마십시오 .
read
접근법은 지역 사회 합의에 의한 모범 사례 접근법 입니다. 주석에서 언급 한주의 사항은 루프가 ffmpeg
stdin에서 읽은 명령 (예 :)을 실행할 때 적용되며 루프에 stdin이 아닌 FD를 사용하거나 이러한 명령의 입력을 리디렉션하여 사소하게 해결됩니다. 반대로, for
-loop 방식 에서 글 로빙 버그를 해결하려면 셸 전역 설정을 변경 한 다음 되돌려 야합니다.
for
루프 접근 방식은 당신이 경우에도 기가 바이트의 데이터가 이상 반복하는 경우는 완전히 사용할 수 없게 모든 콘텐츠는 루프가 전혀 실행을 시작하기 전에 읽어야한다는 것을 여기에 방법을 사용 이 불가능 글 로빙; while read
루프는 하위 프로세스 생성 콘텐츠가 아직 실행 중에 (즉 목적 스트리밍 가능한 임) 실행을 시작할 수 있다는 것을 의미하는 시간에 더 이상 단일 행의 데이터보다 저장할 필요가 없으며, 또한 제한된 메모리 소비를 갖는다.
while
기반 접근 방식에는 * 문자 문제가있는 것으로 보입니다. 위의 답변에 대한 의견을 참조하십시오. 그러나 반 패턴 인 파일에 대한 반복을 반대하지는 않는다.
입력 파일과 사용자 입력 (또는 stdin의 다른 것)을 모두 처리해야하는 경우 다음 해결 방법을 사용하십시오.
#!/bin/bash
exec 3<"$1"
while IFS='' read -r -u 3 line || [[ -n "$line" ]]; do
read -p "> $line (Press Enter to continue)"
done
허용 된 답변 과 bash-hackers 리디렉션 자습서를 기반으로 합니다 .
여기서 스크립트 인수로 전달 된 파일에 대해 파일 설명자 3을 열고이 read
설명자를 입력 ( -u 3
) 으로 사용하도록 지시합니다 . 따라서 기본 입력 설명자 (0)를 터미널이나 다른 입력 소스에 연결하여 사용자 입력을 읽을 수 있습니다.
올바른 오류 처리를 위해
#!/bin/bash
set -Ee
trap "echo error" EXIT
test -e ${FILENAME} || exit
while read -r line
do
echo ${line}
done < ${FILENAME}
다음은 파일 내용을 인쇄합니다.
cat $Path/FileName.txt
while read line;
do
echo $line
done
bash에서 IFS (내장 필드 구분 기호) 도구를 사용하고, 줄을 토큰으로 구분하는 데 사용하는 문자를 정의합니다. 기본적으로 < tab > / < space > / < newLine >
1 단계 : 파일 데이터를로드하고 목록에 삽입하십시오.
# declaring array list and index iterator
declare -a array=()
i=0
# reading file in row mode, insert each line into array
while IFS= read -r line; do
array[i]=$line
let "i++"
# reading from file path
done < "<yourFullFilePath>"
2 단계 : 이제 출력을 반복하고 인쇄합니다.
for line in "${array[@]}"
do
echo "$line"
done
배열의 에코 특정 인덱스 : 배열 의 변수에 액세스 :
echo "${array[0]}"