read non-constant number of files in bash (multiple files in bash)
read non-constant number of files in bash (multiple files in bash)
我有数量未知的 log/text 个文件,我需要使用 Bash 脚本从中读取并对其中的一些变量求和。
问题是我的变量在循环中的每次迭代后重置。
我看到了 ,但是有一定数量的文件(只有两个文件)。
我用 ls 找到了文件的数量。
我使用 cat 从每个文件中读取。
我无法正确保存和添加变量。
这是我尝试做的:
logfiles=($(ls -l ~ | grep -o '[^ ]+$' | grep ${LOG_NAME}log))
num_of_logs=${#logfiles[@]}
for LOG_NUM in `seq 0 $(($num_of_logs-1))`
do (
SPEED=`cat $LOG | grep sum_sent -A7 | grep bits_per_second | tr "," " " | awk '{ SUM+=$NF } END { print SUM } '`
BITS=$(printf '%.0f' ${SPEED})
GIGABITS=$( bc -l <<< "scale=2; $BITS/1000000000" )
GIGASUM=$( echo "$GIGABITS+$GIGASUM" | bc )
)
done `
试过:
将“cat”命令分隔成一个带有数组的单独循环,并将每个结果输入到不同的索引。
产生了相同的结果,数组也为空。
The problem is my variables reset after each iteration in a loop.
是的,因为您将循环体括在括号 ()
中。 subshell 中 运行 内的所有内容,特别是其中的变量定义和更改仅影响 subshell,这在每次迭代中都是新的。如果您希望所有内容都 运行 在同一个 shell 中,则只需省略这些即可。
此外,
您没有为变量 GIGASUM
设置初始值,因此它最初为空(不是 0)。
你在最后一行的末尾有一个反引号 (`)。
$()
替代方法比反引号更具可读性。由于您已经假设 shell 支持该形式,因此您应该始终如一地使用它。
如果变量的值不完全在您的控制之下,通常即使它们完全在您的控制之下,也应该引用其值的扩展。
您不应尝试解析 ls
的输出。通配符有时就足够了, find
服务更普遍。特殊情况下与stat
命令结合使用。解析 ls -l
的输出以删除普通 ls
没有的所有内容尤其没有意义。
你从未设置变量LOG
不清楚为什么要遍历日志数量而不是直接遍历日志文件名。
当您可以通过名称将文件指定给第二个命令时,不要 cat
将文件添加到另一个命令中。
使用空格和换行符使您的代码更清晰。有几个地方您可以自然地换行,而无需转义换行符。
我相信还有更多可用的改进,但这涵盖了以上所有内容:
# Supposing that you actually need the logfiles array for something later,
# after the loop (otherwise, you can put the glob directly into the `for` command):
logfiles=(~/*"${LOG_NAME}"log*)
GIGASUM=0
for LOG in "${logfiles[@]}"; do
SPEED=$(grep sum_sent -A7 "$LOG" |
grep bits_per_second |
tr "," " " |
awk '{ SUM+=$NF } END { print SUM } ')
BITS=$(printf '%.0f' ${SPEED})
GIGABITS=$( bc -l <<< "scale=2; $BITS/1000000000" )
GIGASUM=$( echo "$GIGABITS+$GIGASUM" | bc )
done
我有数量未知的 log/text 个文件,我需要使用 Bash 脚本从中读取并对其中的一些变量求和。
问题是我的变量在循环中的每次迭代后重置。
我看到了
我用 ls 找到了文件的数量。 我使用 cat 从每个文件中读取。 我无法正确保存和添加变量。 这是我尝试做的:
logfiles=($(ls -l ~ | grep -o '[^ ]+$' | grep ${LOG_NAME}log))
num_of_logs=${#logfiles[@]}
for LOG_NUM in `seq 0 $(($num_of_logs-1))`
do (
SPEED=`cat $LOG | grep sum_sent -A7 | grep bits_per_second | tr "," " " | awk '{ SUM+=$NF } END { print SUM } '`
BITS=$(printf '%.0f' ${SPEED})
GIGABITS=$( bc -l <<< "scale=2; $BITS/1000000000" )
GIGASUM=$( echo "$GIGABITS+$GIGASUM" | bc )
)
done `
试过: 将“cat”命令分隔成一个带有数组的单独循环,并将每个结果输入到不同的索引。 产生了相同的结果,数组也为空。
The problem is my variables reset after each iteration in a loop.
是的,因为您将循环体括在括号 ()
中。 subshell 中 运行 内的所有内容,特别是其中的变量定义和更改仅影响 subshell,这在每次迭代中都是新的。如果您希望所有内容都 运行 在同一个 shell 中,则只需省略这些即可。
此外,
您没有为变量
GIGASUM
设置初始值,因此它最初为空(不是 0)。你在最后一行的末尾有一个反引号 (`)。
$()
替代方法比反引号更具可读性。由于您已经假设 shell 支持该形式,因此您应该始终如一地使用它。如果变量的值不完全在您的控制之下,通常即使它们完全在您的控制之下,也应该引用其值的扩展。
您不应尝试解析
ls
的输出。通配符有时就足够了,find
服务更普遍。特殊情况下与stat
命令结合使用。解析ls -l
的输出以删除普通ls
没有的所有内容尤其没有意义。你从未设置变量
LOG
不清楚为什么要遍历日志数量而不是直接遍历日志文件名。
当您可以通过名称将文件指定给第二个命令时,不要
cat
将文件添加到另一个命令中。使用空格和换行符使您的代码更清晰。有几个地方您可以自然地换行,而无需转义换行符。
我相信还有更多可用的改进,但这涵盖了以上所有内容:
# Supposing that you actually need the logfiles array for something later,
# after the loop (otherwise, you can put the glob directly into the `for` command):
logfiles=(~/*"${LOG_NAME}"log*)
GIGASUM=0
for LOG in "${logfiles[@]}"; do
SPEED=$(grep sum_sent -A7 "$LOG" |
grep bits_per_second |
tr "," " " |
awk '{ SUM+=$NF } END { print SUM } ')
BITS=$(printf '%.0f' ${SPEED})
GIGABITS=$( bc -l <<< "scale=2; $BITS/1000000000" )
GIGASUM=$( echo "$GIGABITS+$GIGASUM" | bc )
done