[shell] 쉘에서 변수로 파일을 읽는 방법은 무엇입니까?
파일을 읽고 변수에 저장하고 싶지만 파일을 인쇄하지 않고 변수를 유지해야합니다. 어떻게해야합니까? 이 스크립트를 작성했지만 필요한 것은 아닙니다.
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
스크립트에서 파일 이름을 매개 변수로 제공 할 수 있으므로 파일에 “aaaa”가 포함 된 경우 다음과 같이 인쇄됩니다.
aaaa
11111-----
그러나 이것은 단지 파일을 화면에 출력하고 변수에 저장하고 싶습니다! 이 작업을 수행하는 쉬운 방법이 있습니까?
답변
크로스 플랫폼 최저 공통 분모에서 sh
다음을 사용합니다.
#!/bin/sh
value=`cat config.txt`
echo "$value"
에서 bash
또는 zsh
, 호출하지 않고 변수로 전체 파일을 읽을 수 있습니다 cat
:
#!/bin/bash
value=$(<config.txt)
echo "$value"
호출 cat
에 bash
또는 zsh
파일을 후루룩 소리 내며 먹기하는 것이 고려 될 것이다 고양이의 쓸모없는 사용 .
줄 바꿈을 유지하기 위해 명령 대체를 인용 할 필요는 없습니다.
Bash Hacker의 Wiki- 명령 대체-전문 분야를 참조하십시오 .
답변
전체 파일을 변수로 읽으려면 다음을 수행하십시오.
#!/bin/bash
value=`cat sources.xml`
echo $value
한 줄씩 읽으려면 다음을 수행하십시오.
while read line; do
echo $line
done < file.txt
답변
두 가지 중요한 함정
지금까지 다른 답변에서 무시되었습니다.
- 명령 확장에서 후행 줄 바꿈 제거
- 널 문자 제거
명령 확장에서 후행 줄 바꿈 제거
이것은 다음에 대한 문제입니다.
value="$(cat config.txt)"
read
기반 솔루션 에는 적합하지 않습니다 .
명령 확장은 후행 줄 바꿈을 제거합니다.
S="$(printf "a\n")"
printf "$S" | od -tx1
출력 :
0000000 61
0000001
이것은 파일에서 읽는 순진한 방법을 깨뜨립니다.
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
POSIX 해결 방법 : 명령 확장에 추가 문자를 추가하고 나중에 제거하십시오.
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
출력 :
0000000 61 0a 0a
0000003
거의 POSIX 해결 방법 : ASCII 인코딩. 아래를 참조하십시오.
널 문자 제거
NUL 문자를 변수에 저장하는 깔끔한 Bash 방법은 없습니다 .
이는 확장과 read
솔루션 모두에 영향을 미치며 이에 대한 좋은 해결 방법을 모릅니다.
예:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
출력 :
0000000 61 00 62
0000003
0000000 61 62
0000002
하, 우리의 NUL이 사라졌습니다!
해결 방법 :
-
ASCII 인코딩 아래를 참조하십시오.
-
bash 확장
$""
리터럴을 사용하십시오.S=$"a\0b" printf "$S" | od -tx1
리터럴에만 작동하므로 파일을 읽는 데 유용하지 않습니다.
함정에 대한 해결 방법
uuencode base64로 인코딩 된 파일 버전을 변수에 저장하고 매번 사용하기 전에 디코딩하십시오.
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
산출:
0000000 61 00 0a
0000003
uuencode와 udecode는 POSIX 7 이지만 기본적으로 Ubuntu 12.04에는 없습니다 ( sharutils
패키지) … <()
다른 파일에 쓰는 것을 제외하고 bash 프로세스 대체 확장에 대한 POSIX 7 대안이 보이지 않습니다 …
물론 이것은 느리고 불편하기 때문에 실제 대답은 다음과 같습니다. 입력 파일에 NUL 문자가 포함될 수 있으면 Bash를 사용하지 마십시오.
답변
이것은 나를 위해 작동합니다 :
v=$(cat <file_path>)
echo $v
답변
로 치로 틸리 노트 후행 줄 바꿈을 삭제합니다 명령 대체를 사용하여. 후행 문자를 추가하는 해결 방법은 훌륭하지만 꽤 오랫동안 사용한 후에 명령 대체를 전혀 사용하지 않는 솔루션이 필요하다고 결정했습니다.
내 접근 방식은 이제 stdin의 내용을 변수로 직접 읽기 위해 내장 플래그read
와 함께 사용 합니다.printf
-v
# Reads stdin into a variable, accounting for trailing newlines. Avoids needing a subshell or
# command substitution.
read_input() {
# Use unusual variable names to avoid colliding with a variable name
# the user might pass in (notably "contents")
: "${1:?Must provide a variable to read into}"
if [[ "$1" == '_line' || "$1" == '_contents' ]]; then
echo "Cannot store contents to $1, use a different name." >&2
return 1
fi
local _line _contents
while read -r _line; do
_contents="${_contents}${_line}"$'\n'
done
_contents="${_contents}${_line}" # capture any content after the last newline
printf -v "$1" '%s' "$_contents"
}
후행 줄 바꿈이 있거나없는 입력을 지원합니다.
사용법 예 :
$ read_input file_contents < /tmp/file
# $file_contents now contains the contents of /tmp/file
답변
for 루프로 한 번에 한 줄에 액세스 할 수 있습니다
#!/bin/bash -eu
#This script prints contents of /etc/passwd line by line
FILENAME='/etc/passwd'
I=0
for LN in $(cat $FILENAME)
do
echo "Line number $((I++)) --> $LN"
done
전체 내용을 File (예 : line.sh)에 복사하십시오. 실행
chmod +x line.sh
./line.sh