如何将文件读入Shell中的变量?

本文讨论如何在Shell脚本中将文件内容读入变量,重点介绍了命令扩展时尾随换行符的删除和NUL字符的问题,并提供了解决方案,包括使用uuencode/base64编码和内建的read命令来避免这些问题。
摘要由CSDN通过智能技术生成

本文翻译自: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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值