本文翻譯自: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
: 在bash
或zsh
,無需調用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 . 在bash
或zsh
調用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: 到目前爲止,其他答案都忽略了這些答案:
- Trailing newline removal from command expansion 從命令擴展中刪除尾隨換行符
- 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 $v
: v=$(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