如何将文件读入 Bash 中引号数量未知的变量
How do I read a file into a variable with an unknown number of quotes in Bash
我尝试使用 git-bash
将文件读入变量。我正在使用这样的东西:
readFile() {
local file=""
local resultVar=""
eval $resultVar="'$(cat ${file})'"
}
与这里的建议类似 Link。
这在大多数情况下都可以正常工作。但它可能会导致问题,具体取决于文件中的引号数量。例如:
例一 ❌
test1.txt
:
text "quoted"
code
:
$ echo "text \"quoted\"" > test1.txt &&
> readFile "./test1.txt" test1 &&
> printf "test1: %s\n" "${test1}"
test1: text "quoted"
错误:尾随 \n
的剪辑在末尾。
例子2 ❌
test2.txt
:
text "one quote
code
:
$ echo "text \"one quote" > test2.txt &&
> readFile "./test2.txt" test2 &&
> printf "test2: %s\n" "${test2}"
test2: text "one quote
错误:尾随 \n
的剪辑在末尾。
例3 ❌
test3.txt
:
text 'quoted'
code
:
$ echo "text 'quoted'" > test3.txt &&
> readFile "./test3.txt" test3 &&
> printf "test3: %s\n" "${test3}"
test3: text quoted
错误:这些single-quotes
已被删除!
范例 4 ❌
test4.txt
:
text 'one quote
code
:
$ echo "text 'one quote" > test4.txt &&
> readFile "./test4.txt" test4 &&
> printf "test4: %s\n" "${test4}"
bash: unexpected EOF while looking for matching `''
bash: syntax error: unexpected end of file
错误:这变得更糟了...
范例 5 ❌
test5.txt
:
text 'quoted"
code
:
$ echo "text \'quoted\"" > test5.txt &&
> readFile "./test5.txt" test5 &&
> printf "test5: %s\n" "${test5}"
bash: unexpected EOF while looking for matching `"'
bash: syntax error: unexpected end of file
ERROR: 同上。
那么,我如何在不知道它是否包含引号、包含多少引号以及包含何种类型的引号的情况下,将函数中的文件稳健地读取到变量中?
也许还有其他字符也可以破坏我的代码,但我没有检查。如果解决方案也能解决这些问题,那就太好了。
不要使用 eval。
在 bash
中,您可以 $(<file)
而不是 $(cat file)
。只是快了一点。
您可以使用名称参考:
readFile() {
declare -n resultVar=
resultVar="$(<"")"
}
如果没有零字节,您可以使用readarray/mapfile。注意 - 它将保留尾随换行符,而不是 $(...)
删除尾随换行符:
readFile() {
readarray -d '' -t "" < ""
}
如果你真的想用eval
,那就用declare
:
readFile() {
declare -g "=$(< "")"
}
如果您真的很想使用 eval
,请始终将正确转义的字符串传递给它,即。总是在 printf "%q"
:
之后
readFile() {
eval "$(printf "%q" "")=$(printf "%q" "$(< "")")"
}
这样可以实现你想要的吗?
#!/usr/bin/env bash
readFile() {
IFS= read -rd '' "" < ""
}
readFile var data-file
# Checking result
printf %s "$var" | xxd
我尝试使用 git-bash
将文件读入变量。我正在使用这样的东西:
readFile() {
local file=""
local resultVar=""
eval $resultVar="'$(cat ${file})'"
}
与这里的建议类似 Link。
这在大多数情况下都可以正常工作。但它可能会导致问题,具体取决于文件中的引号数量。例如:
例一 ❌
test1.txt
:
text "quoted"
code
:
$ echo "text \"quoted\"" > test1.txt &&
> readFile "./test1.txt" test1 &&
> printf "test1: %s\n" "${test1}"
test1: text "quoted"
错误:尾随 \n
的剪辑在末尾。
例子2 ❌
test2.txt
:
text "one quote
code
:
$ echo "text \"one quote" > test2.txt &&
> readFile "./test2.txt" test2 &&
> printf "test2: %s\n" "${test2}"
test2: text "one quote
错误:尾随 \n
的剪辑在末尾。
例3 ❌
test3.txt
:
text 'quoted'
code
:
$ echo "text 'quoted'" > test3.txt &&
> readFile "./test3.txt" test3 &&
> printf "test3: %s\n" "${test3}"
test3: text quoted
错误:这些single-quotes
已被删除!
范例 4 ❌
test4.txt
:
text 'one quote
code
:
$ echo "text 'one quote" > test4.txt &&
> readFile "./test4.txt" test4 &&
> printf "test4: %s\n" "${test4}"
bash: unexpected EOF while looking for matching `''
bash: syntax error: unexpected end of file
错误:这变得更糟了...
范例 5 ❌
test5.txt
:
text 'quoted"
code
:
$ echo "text \'quoted\"" > test5.txt &&
> readFile "./test5.txt" test5 &&
> printf "test5: %s\n" "${test5}"
bash: unexpected EOF while looking for matching `"'
bash: syntax error: unexpected end of file
ERROR: 同上。
那么,我如何在不知道它是否包含引号、包含多少引号以及包含何种类型的引号的情况下,将函数中的文件稳健地读取到变量中?
也许还有其他字符也可以破坏我的代码,但我没有检查。如果解决方案也能解决这些问题,那就太好了。
不要使用 eval。
在 bash
中,您可以 $(<file)
而不是 $(cat file)
。只是快了一点。
您可以使用名称参考:
readFile() {
declare -n resultVar=
resultVar="$(<"")"
}
如果没有零字节,您可以使用readarray/mapfile。注意 - 它将保留尾随换行符,而不是 $(...)
删除尾随换行符:
readFile() {
readarray -d '' -t "" < ""
}
如果你真的想用eval
,那就用declare
:
readFile() {
declare -g "=$(< "")"
}
如果您真的很想使用 eval
,请始终将正确转义的字符串传递给它,即。总是在 printf "%q"
:
readFile() {
eval "$(printf "%q" "")=$(printf "%q" "$(< "")")"
}
这样可以实现你想要的吗?
#!/usr/bin/env bash
readFile() {
IFS= read -rd '' "" < ""
}
readFile var data-file
# Checking result
printf %s "$var" | xxd