Wil*_*ard 6 bash shell-script read
(为简单起见,我假设要读取的文件是第一个参数 - $1。)
我可以在外部做我想做的事:
tempfile=$(mktemp)
awk '/^#/ {next}; NF == 0 {next}; {print}' "$1" > $tempfile
while read var1 var2 var3 var4 < $tempfile; do
# stuff with var1, etc.
done
Run Code Online (Sandbox Code Playgroud)
但是,awk每次解析配置文件时都需要调用似乎很荒谬。有没有办法read忽略文件中的注释行或空白行,而没有外部二进制文件/潜在的性能问题?
到目前为止的答案非常有帮助!澄清一下,我不想使用临时文件,但我确实想从文件中读取配置,而不是从标准中读取配置。我很清楚在调用脚本时可以使用输入重定向,但是由于各种原因在我的情况下不起作用。
我想对要读取的输入进行软编码,例如:
configfile="/opt/myconfigfile.txt"
[ $# -gt 0 ] && [ -r "$1" ] && configfile="$1"
while read var1 var2 var3 var4 < "$configfile" ; do
...
Run Code Online (Sandbox Code Playgroud)
但是当我尝试这个时,它只是configfile一遍又一遍地读取第一行,直到我终止进程。
也许这应该是它自己的问题......但它可能与我正在做的事情不同。我的错误在哪里?
您不需要临时文件来执行此操作,并且 sed(或 awk)在注释处理方面比 shell case 语句灵活得多。
例如:
configfile='/opt/myconfigfile.txt'
[ $# -gt 0 ] && [ -r "$1" ] && configfile="$1"
sed -e 's/[[:space:]]*#.*// ; /^[[:space:]]*$/d' "$configfile" |
while read var1 var2 var3 var4; do
# stuff with var1, etc.
done
# Note: var1 etc are not available to the script at this
# point. They are only available in the sub-shell running
# the while loop, and go away when that sub-shell ends.
Run Code Online (Sandbox Code Playgroud)
这会删除注释(带或不带前导空格)并从输入中删除空行,然后再将其输送到 while 循环中。它单独处理行上的注释以及附加到行尾的注释:
# full-line comment
# var1 var2 var3 var4
abc 123 xyz def # comment here
Run Code Online (Sandbox Code Playgroud)
像这样的呼叫sed或awk任务并不“荒谬”,而是完全正常的。这就是这些工具的用途。至于性能,我敢打赌,除了非常小的输入文件之外,该sed版本会快得多。管道传输sed有一些启动开销,但运行速度非常快,而 shell 则很慢。
请注意,当 while 循环结束时,在 while read 循环中设置的变量(var1、var2、var3 等)将“超出范围”。只能在 while 循环内部使用。while 循环正在子 shell 中运行,因为配置文件通过管道传输到其中。当该子 shell 死亡时,它的环境也随之消失 - 并且子进程无法更改其父进程的环境。
如果您希望变量在 while 循环后保留其值,则需要避免使用管道。例如,使用输入重定向 ( <) 和进程替换( <(...)):
while read var1 var2 var3 var4; do
# stuff with var1, etc.
done < <(sed -e 's/[[:space:]]*#.*// ; /^[[:space:]]*$/d' "$configfile")
# remainder of script can use var1 etc if and as needed.
Run Code Online (Sandbox Code Playgroud)
使用此进程替换版本,while 循环在父 shell 中运行,并且sed脚本作为子进程运行(其输出重定向到 while 循环)。sed 及其环境在完成后消失,而运行 while 循环的 shell 保留循环创建/更改的变量。