[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"

호출 catbash또는 zsh파일을 후루룩 소리 내며 먹기하는 것이 고려 될 것이다 고양이의 쓸모없는 사용 .

줄 바꿈을 유지하기 위해 명령 대체를 인용 할 필요는 없습니다.

Bash Hacker의 Wiki- 명령 대체-전문 분야를 참조하십시오 .


답변

전체 파일을 변수로 읽으려면 다음을 수행하십시오.

#!/bin/bash
value=`cat sources.xml`
echo $value

한 줄씩 읽으려면 다음을 수행하십시오.

while read line; do
    echo $line
done < file.txt


답변

두 가지 중요한 함정

지금까지 다른 답변에서 무시되었습니다.

  1. 명령 확장에서 후행 줄 바꿈 제거
  2. 널 문자 제거

명령 확장에서 후행 줄 바꿈 제거

이것은 다음에 대한 문제입니다.

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


답변