如何將文件讀入Shell中的變量?

本文翻譯自:How to read a file into a variable in shell?

I want to read a file and save it in variable, but I need to keep the variable and not just print out the file. 我想讀取文件並將其保存在變量中,但我需要保留變量,而不僅僅是打印文件。 How can I do this? 我怎樣才能做到這一點? I have written this script but it isn't quite what I needed: 我已經編寫了此腳本,但它並不是我所需要的:

#!/bin/sh
while read LINE  
do  
  echo $LINE  
done <$1  
echo 11111-----------  
echo $LINE  

In my script, I can give the file name as a parameter, so, if the file contains "aaaa", for example, it would print out this: 在我的腳本中,我可以將文件名作爲參數,因此,例如,如果文件包含“ aaaa”,它將輸出以下內容:

aaaa
11111-----

But this just prints out the file onto the screen, and I want to save it into a variable! 但這只是將文件打印到屏幕上,我想將其保存到變量中! Is there an easy way to do this? 是否有捷徑可尋?


#1樓

參考:https://stackoom.com/question/VAAY/如何將文件讀入Shell中的變量


#2樓

In cross-platform, lowest-common-denominator sh you use: 在跨平臺的最小公分母sh您可以使用:

#!/bin/sh
value=`cat config.txt`
echo "$value"

In bash or zsh , to read a whole file into a variable without invoking cat : bashzsh ,無需調用cat即可將整個文件讀入變量:

#!/bin/bash
value=$(<config.txt)
echo "$value"

Invoking cat in bash or zsh to slurp a file would be considered a Useless Use of Cat . bashzsh調用cat來處理文件將被視爲Cat無用

Note that it is not necessary to quote the command substitution to preserve newlines. 請注意,不必引用命令替換來保留換行符。

See: Bash Hacker's Wiki - Command substitution - Specialities . 請參閱: Bash Hacker的Wiki-命令替代-Specialties


#3樓

Two important pitfalls 兩個重要的陷阱

which were ignored by other answers so far: 到目前爲止,其他答案都忽略了這些答案:

  1. Trailing newline removal from command expansion 從命令擴展中刪除尾隨換行符
  2. NUL character removal NUL字符刪除

Trailing newline removal from command expansion 從命令擴展中刪除尾隨換行符

This is a problem for the: 這是一個問題:

value="$(cat config.txt)"

type solutions, but not for read based solutions. 類型解決方案,但不適用於基於read的解決方案。

Command expansion removes trailing newlines: 命令擴展刪除尾隨的換行符:

S="$(printf "a\n")"
printf "$S" | od -tx1

Outputs: 輸出:

0000000 61
0000001

This breaks the naive method of reading from files: 這打破了從文件讀取的幼稚方法:

FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"

POSIX workaround: append an extra char to the command expansion and remove it later: POSIX解決方法:在命令擴展中附加一個額外的字符,並在以後將其刪除:

S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1

Outputs: 輸出:

0000000 61 0a 0a
0000003

Almost POSIX workaround: ASCII encode. 幾乎是POSIX的解決方法:ASCII編碼。 See below. 見下文。

NUL character removal NUL字符刪除

There is no sane Bash way to store NUL characters in variables . 沒有理智的Bash方法將NUL字符存儲在變量中

This affects both expansion and read solutions, and I don't know any good workaround for it. 這會影響擴展和read解決方案,而且我不知道有什麼好的解決方法。

Example: 例:

printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1

Outputs: 輸出:

0000000 61 00 62
0000003

0000000 61 62
0000002

Ha, our NUL is gone! 哈,我們的NUL不見了!

Workarounds: 解決方法:

  • ASCII encode. ASCII編碼。 See below. 見下文。

  • use bash extension $"" literals: 使用bash擴展名$""文字:

     S=$"a\\0b" printf "$S" | od -tx1 

    Only works for literals, so not useful for reading from files. 僅適用於文字,因此對從文件讀取無用。

Workaround for the pitfalls 陷阱的解決方法

Store an uuencode base64 encoded version of the file in the variable, and decode before every usage: 將文件的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"

Output: 輸出:

0000000 61 00 0a
0000003

uuencode and udecode are POSIX 7 but not in Ubuntu 12.04 by default ( sharutils package)... I don't see a POSIX 7 alternative for the bash process <() substitution extension except writing to another file... uuencode和udecode是POSIX 7,但默認情況下不在Ubuntu 12.04中( sharutils軟件包)...除了寫到另一個文件外,我看不到bash進程<()替換擴展名的POSIX 7替代品...

Of course, this is slow and inconvenient, so I guess the real answer is: don't use Bash if the input file may contain NUL characters. 當然,這很慢且很不方便,所以我想真正的答案是:如果輸入文件中可能包含NUL字符,請不要使用Bash。


#4樓

As Ciro Santilli notes using command substitutions will drop trailing newlines. 正如Ciro Santilli指出的那樣,使用命令替換將刪除尾隨的換行符。 Their workaround adding trailing characters is great, but after using it for quite some time I decided I needed a solution that didn't use command substitution at all. 他們添加尾隨字符的解決方法很棒,但是使用了一段時間後,我決定需要一個根本不使用命令替換的解決方案。

My approach now uses read along with the printf builtin's -v flag in order to read the contents of stdin directly into a variable. 現在, 我的方法read與內置的printf-v標誌一起使用,以便將stdin的內容直接讀入變量。

# 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"
}

This supports inputs with or without trailing newlines. 這支持帶或不帶尾隨換行符的輸入。

Example usage: 用法示例:

$ read_input file_contents < /tmp/file
# $file_contents now contains the contents of /tmp/file

#5樓

這對我v=$(cat <file_path>) echo $vv=$(cat <file_path>) echo $v


#6樓

You can access 1 line at a time by for loop 您可以通過for循環一次訪問1行

#!/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

Copy the entire content to File (say line.sh ) ; 將整個內容複製到File(例如line.sh); Execute 執行

chmod +x line.sh
./line.sh
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章