将文件输出限制为仅 2 行
limiting file output to only 2 lines
我 ping 了一系列地址并将延迟结果附加到一个文件中(每个地址都有一个单独的文件)。我正在尝试将文件限制为仅包含最后 2 个条目。
$outpath=/opt/blah/file.txt
resp_str="0.42"
echo $resp_str >> $outpath
tail -2 $outpath > $outpath
如果没有 tail,文件会随着新数据的增加而继续增长(本例中仅为 .42)。但是当我调用 tail 时,它会写出一个空文件。如果我将尾部输出重定向到一个不同名称的文件,那么我会得到预期的结果。我可以在阅读文件时不写出文件吗?有没有简单的解决办法?
这是完整的脚本:
OUT_PATH=/opt/blah/sites/
TEST_FILE=/opt/blah/test.txt
while IFS=, read -r ip name; do
if [[ "$ip" != \#* ]]; then
RESP_STR=$( ping -c 1 -q $ip | grep rtt| awk '{print }' | awk -F/ '{ print ; }')
echo $RESP_STR >> "$OUT_PATH""test/"$name".txt"
fi
done << $TEST_FILE
您可以使用管道 |
将一个命令的输出发送到另一个命令,在本例中为 tail.
然后我们可以使用 >>
追加到文件中。如果我们使用 >
,我们每次都会覆盖文件,所有以前的内容都会丢失。
此示例每次将目录中的最后 2 个文件写入 log.txt 运行.
ls | tail -2 >> log.txt
假设:
- 需要为并行、并发进程编写代码(使用临时文件将要求每个进程都有一个唯一命名的临时文件)
- 继续编写支持大量操作的代码(即减少 creating/destroying 临时文件的开销)
使用 mktemp
创建临时文件的一个想法......我们将其包装在一个函数中以便于使用:
keep2 () {
# Usage: keep2 filename "new line of text"
[[ ! -f "${tmpfile}" ]] &&
tmpfile=$(mktemp)
tail -1 "" > "${tmpfile}"
{ cat "${tmpfile}"; echo ""; } > ""
}
备注:
- 硬编码的
-1
(tail -1
) 可以参数化或引用 user-defined 环境变量
- OP可以根据需要更改输入参数的顺序
参加试驾;
> logfile
for ((i=1;i<=5;i++))
do
echo "######### $i"
keep2 logfile "$i"
cat logfile
done
这会生成:
######### 1
1
######### 2
1
2
######### 3
2
3
######### 4
3
4
######### 5
4
5
在 OP 的代码中,以下行:
echo $RESP_STR >> "$OUT_PATH""test/"$name".txt"
将替换为:
keep2 "$OUT_PATH""test/"$name".txt" "${RESP_STR}"
tail -2 $outpath > $outpath
>
在 tail
开始读取之前截断文件。
您需要缓冲 tail
的输出,然后再将其写回该文件。使用 sponge 实现:
tail -2 $outpath | sponge $outpath
我 ping 了一系列地址并将延迟结果附加到一个文件中(每个地址都有一个单独的文件)。我正在尝试将文件限制为仅包含最后 2 个条目。
$outpath=/opt/blah/file.txt
resp_str="0.42"
echo $resp_str >> $outpath
tail -2 $outpath > $outpath
如果没有 tail,文件会随着新数据的增加而继续增长(本例中仅为 .42)。但是当我调用 tail 时,它会写出一个空文件。如果我将尾部输出重定向到一个不同名称的文件,那么我会得到预期的结果。我可以在阅读文件时不写出文件吗?有没有简单的解决办法?
这是完整的脚本:
OUT_PATH=/opt/blah/sites/
TEST_FILE=/opt/blah/test.txt
while IFS=, read -r ip name; do
if [[ "$ip" != \#* ]]; then
RESP_STR=$( ping -c 1 -q $ip | grep rtt| awk '{print }' | awk -F/ '{ print ; }')
echo $RESP_STR >> "$OUT_PATH""test/"$name".txt"
fi
done << $TEST_FILE
您可以使用管道 |
将一个命令的输出发送到另一个命令,在本例中为 tail.
然后我们可以使用 >>
追加到文件中。如果我们使用 >
,我们每次都会覆盖文件,所有以前的内容都会丢失。
此示例每次将目录中的最后 2 个文件写入 log.txt 运行.
ls | tail -2 >> log.txt
假设:
- 需要为并行、并发进程编写代码(使用临时文件将要求每个进程都有一个唯一命名的临时文件)
- 继续编写支持大量操作的代码(即减少 creating/destroying 临时文件的开销)
使用 mktemp
创建临时文件的一个想法......我们将其包装在一个函数中以便于使用:
keep2 () {
# Usage: keep2 filename "new line of text"
[[ ! -f "${tmpfile}" ]] &&
tmpfile=$(mktemp)
tail -1 "" > "${tmpfile}"
{ cat "${tmpfile}"; echo ""; } > ""
}
备注:
- 硬编码的
-1
(tail -1
) 可以参数化或引用 user-defined 环境变量 - OP可以根据需要更改输入参数的顺序
参加试驾;
> logfile
for ((i=1;i<=5;i++))
do
echo "######### $i"
keep2 logfile "$i"
cat logfile
done
这会生成:
######### 1
1
######### 2
1
2
######### 3
2
3
######### 4
3
4
######### 5
4
5
在 OP 的代码中,以下行:
echo $RESP_STR >> "$OUT_PATH""test/"$name".txt"
将替换为:
keep2 "$OUT_PATH""test/"$name".txt" "${RESP_STR}"
tail -2 $outpath > $outpath
>
在 tail
开始读取之前截断文件。
您需要缓冲 tail
的输出,然后再将其写回该文件。使用 sponge 实现:
tail -2 $outpath | sponge $outpath