다음 .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효과적으로 루프를 벗어날 수 있습니다. 아마도 이것에 대한 좋은 이유가 있지만 이것을 발견하기 전에 코드가 실패하는 원인을 알아내는 데 시간이 걸렸습니다.
ffmpegstdin 을 소비 하여 발생합니다 . 추가 </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접근법은 지역 사회 합의에 의한 모범 사례 접근법 입니다. 주석에서 언급 한주의 사항은 루프가 ffmpegstdin에서 읽은 명령 (예 :)을 실행할 때 적용되며 루프에 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]}"