![shell - 从日志中提取日期和时间](https://linux22.com/image/150011/shell%20-%20%E4%BB%8E%E6%97%A5%E5%BF%97%E4%B8%AD%E6%8F%90%E5%8F%96%E6%97%A5%E6%9C%9F%E5%92%8C%E6%97%B6%E9%97%B4.png)
我的网络服务器日志文件如下所示:
2001:67c:1220:80c:d4:985a:df2c:d717 - - [22/Feb/2019:07:49:01 +0100] "GET / HTTP/1.1" 200 58266 "-" "curl/7.61.1"
2001:67c:1220:80c:d4:985a:df2c:d717 - - [22/Feb/2019:08:49:01 +0100] "GET / HTTP/1.1" 200 58341 "-" "curl/7.61.1"
2001:67c:1220:808::93e5:8ad - - [22/Feb/2019:08:56:10 +0100] "POST /wp-cron.php?doing_wp_cron=1550822170.2184400558471679687500 HTTP/1.1" 200 3279 "https://ios-example.com/wp-cron.php?doing_wp_cron=1550822170.2184400558471679687500" "WordPress/4.9.9; https://ios-example.com"
...
我需要以这种格式提取日期和时间22/Feb/2019:07:49:01
。
这就是我现在所拥有的(无耻地从这个线程复制:从行中提取日期字段):
file="filename"
while IFS= read -r line
do
echo "`cut -d '[' -f2 $line | cut -d ' ' -f1`" # echoing now for testing purposes
done <"$file"
这是我运行脚本时的输出:
cut: '2001:67c:1220:80c:d4:985a:df2c:d717': Adresář nebo soubor neexistuje
cut: '[22/Feb/2019:07:49:01': Adresář nebo soubor neexistuje
cut: +0100]: Adresář nebo soubor neexistuje
cut: '"GET': Adresář nebo soubor neexistuje
cut: /: je adresářem
cut: 'HTTP/1.1"': Adresář nebo soubor neexistuje
cut: 200: Adresář nebo soubor neexistuje
cut: 58266: Adresář nebo soubor neexistuje
cut: '"-"': Adresář nebo soubor neexistuje
cut: '"curl/7.61.1"': Adresář nebo soubor neexistuje
22/Feb/2019:08:49:01
22/Feb/2019:08:56:10
22/Feb/2019:08:56:10
22/Feb/2019:09:24:33
22/Feb/2019:09:24:33
22/Feb/2019:09:43:13
22/Feb/2019:09:43:24
...
“Adresář nebo soubor neexistuje”的意思是“目录或文件不存在”。
由于我不知道的原因,它不适用于日志文件的第一行,但适用于文件的其余部分。
答案1
你犯了多个错误:
- cut 使用文件名作为参数
- 你忘记了一些双引号(”)
因此,如果我重写您的示例,并进行最少的更改:
- 指某东西的用途$(代替`。这更加稳健并且可以递归。
- 指某东西的用途${VARIABLE_NAME}而不是 $VARIABLE_NAME 。这更稳健
的新版本
file="filename"
while IFS= read -r line
do
EXTRACT_DATE=$( echo "$line" | cut -d '[' -f2 | cut -d ' ' -f1 )
echo "${EXTRACT_DATE}"
done <"$file"
答案2
造成错误的主要问题是您使用读取行作为读取的$line
文件名。cut
您还可以用来echo
输出命令替换的结果。这是一种反模式。只需运行管道,无需echo
替换命令。它会自行将结果输出到终端。
在这里,我们使用printf
给出cut
从文件中读取的行:
file="filename"
while IFS= read -r line; do
printf '%s\n' "$line" | cut -d '[' -f2 | cut -d ' ' -f1
done <"$file"
接下来要注意的是while
循环是完全不必要的。您拨打cut
两次电话是为了每行在日志文件中。该cut
实用程序完全能够自行逐行读取文件:
file="filename"
cut -d '[' -f2 "$file" | cut -d ' ' -f1
或者,您可以使用 GNU grep
:
grep -oP '(?<=\[)[^ ]+' "$file"
(这将提取第一个之后的第一个空格之前的所有内容[
)
或标准sed
,
sed 's/\].*//; s/.*\[//; s/ .*//' "$file"
(这会删除第一个之后的所有内容]
,然后删除第一个之后的所有内容[
,然后删除空格以及其余内容)
有关的: