将 awk 模式匹配的字段传递给 shell 日期命令替换
Passing field from awk pattern match into shell date command substitution
我想将 (ISO 8601) 日期从 YYYY-MM-DD
转换为 Mon, 03 Dec 2021 00:00:00 -0600
(RFC-822 / RFC 5322)。我找不到解决此特定问题的问题。
我有一个 RSS XML 文件,如下所示:
bash-5.1$ cat feed.xml
<rss version="2.0">
<channel>
<title>Title string</title>
<link>https://domain/feed.xml</link>
<description>Description string here</description>
<language>en-us</language>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>2021-12-03</pubDate>
</item>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>2019-08-13</pubDate>
</item>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>2018-11-23</pubDate>
</item>
</channel>
</rss>
我期望解析后的输出是这样的:
...
<pubDate>Fri, 03 Dec 2021 00:00:00 -0600</pubDate>
...
<pubDate>Tue, 13 Aug 2019 00:00:00 -0500</pubDate>
...
<pubDate>Fri, 23 Nov 2018 00:00:00 -0600</pubDate>
...
通常可以使用 bash date
命令实现此输出,如下所示:
bash-5.1$ date -d "2018-11-23" +"%a, %d %b %Y %T %z"
Fri, 23 Nov 2018 00:00:00 -0600
我正在尝试使用 awk
来完成此操作,因为我了解到命令替换是可能的,而且我相信我很接近,但还不完全是:
bash-5.1$ awk -F "[><]" -v date="$(date +"%a, %d %b %Y %T %z" -d "")" '/pubDate/ {print date}' feed.xml
2021-12-03Sun, 05 Dec 2021 00:00:00 -0600
2019-08-13Sun, 05 Dec 2021 00:00:00 -0600
2018-11-23Sun, 05 Dec 2021 00:00:00 -0600
似乎模式匹配和日期命令一样成功执行,但是 awk </code> 字段看起来没有被传递到 shell <code>date
命令等显示的是当前时间,而不是转换后的时间。
如何将 awk 模式匹配中的
字段传递给日期命令,以便它可以根据字段值转换日期?
非常感谢任何帮助!
稍微更改您的 awk
代码。
$ awk -v date="$(date +"%a, %d %b %Y %T %z")" 'BEGIN {FS=OFS=">"}~/pubDate/{split(,a,"<"); a[1]=date; =a[1]"<"a[2]}1' input_file
<rss version=2.0>
<channel>
<title>Title string</title>
<link>https://domain/feed.xml</link>
<description>Description string here</description>
<language>en-us</language>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>Mon, 06 Dec 2021 00:00:00 +0000</pubDate>
</item>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>Mon, 06 Dec 2021 00:00:00 +0000</pubDate>
</item>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>Mon, 06 Dec 2021 00:00:00 +0000</pubDate>
</item>
</channel>
</rss>
sed
如果设置了变量也可以使用
$ date="$(date +"%a, %d %b %Y %T %z")"
$ sed "/pubDate/ s/....-..-../$date/" input_file
如评论,一般情况下推荐使用xml解析工具。
如果 xml 文件与提供的示例完全对齐,bash
或 awk
可能在有限的条件下工作。
随着 bash:
#!/bin/bash
while IFS= read -r line; do
if [[ $line =~ (.*<pubDate>)([0-9]{4}-[0-9]{2}-[0-9]{2})(</pubDate>.*) ]]; then
datestr=$(date -d "${BASH_REMATCH[2]}" +"%a, %d %b %Y %T %z")
line="${BASH_REMATCH[1]}$datestr${BASH_REMATCH[3]}"
fi
echo "$line"
done < feed.xml
条件 $line =~ (.*<pubDate>)([0-9]{4}-[0-9]{2}-[0-9]{2})(</pubDate>.*)
匹配 <pubdate>
行分配 bash 变量 ${BASH_REMATCH[@]
带括号的子字符串。然后 line
使用重新格式化的日期字符串重建。
如果gawk
支持mktime()
和strftime()
功能,可以
也说 gawk
:
awk '
{
if (match([=11=], /^(.*<pubDate>)([0-9]{4})-([0-9]{2})-([0-9]{2})(<\/pubDate>.*)/, a) ) {
ts = mktime(a[2] " " a[3] " " a[4] " 00 00 00") # timestamp since the epoch
datestr = strftime("%a, %d %b %Y %T %z", ts)
[=11=] = a[1] datestr a[5]
}
} 1' feed.xml
我想将 (ISO 8601) 日期从 YYYY-MM-DD
转换为 Mon, 03 Dec 2021 00:00:00 -0600
(RFC-822 / RFC 5322)。我找不到解决此特定问题的问题。
我有一个 RSS XML 文件,如下所示:
bash-5.1$ cat feed.xml
<rss version="2.0">
<channel>
<title>Title string</title>
<link>https://domain/feed.xml</link>
<description>Description string here</description>
<language>en-us</language>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>2021-12-03</pubDate>
</item>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>2019-08-13</pubDate>
</item>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>2018-11-23</pubDate>
</item>
</channel>
</rss>
我期望解析后的输出是这样的:
...
<pubDate>Fri, 03 Dec 2021 00:00:00 -0600</pubDate>
...
<pubDate>Tue, 13 Aug 2019 00:00:00 -0500</pubDate>
...
<pubDate>Fri, 23 Nov 2018 00:00:00 -0600</pubDate>
...
通常可以使用 bash date
命令实现此输出,如下所示:
bash-5.1$ date -d "2018-11-23" +"%a, %d %b %Y %T %z"
Fri, 23 Nov 2018 00:00:00 -0600
我正在尝试使用 awk
来完成此操作,因为我了解到命令替换是可能的,而且我相信我很接近,但还不完全是:
bash-5.1$ awk -F "[><]" -v date="$(date +"%a, %d %b %Y %T %z" -d "")" '/pubDate/ {print date}' feed.xml
2021-12-03Sun, 05 Dec 2021 00:00:00 -0600
2019-08-13Sun, 05 Dec 2021 00:00:00 -0600
2018-11-23Sun, 05 Dec 2021 00:00:00 -0600
似乎模式匹配和日期命令一样成功执行,但是 awk </code> 字段看起来没有被传递到 shell <code>date
命令等显示的是当前时间,而不是转换后的时间。
如何将 awk 模式匹配中的 字段传递给日期命令,以便它可以根据字段值转换日期?
非常感谢任何帮助!
稍微更改您的 awk
代码。
$ awk -v date="$(date +"%a, %d %b %Y %T %z")" 'BEGIN {FS=OFS=">"}~/pubDate/{split(,a,"<"); a[1]=date; =a[1]"<"a[2]}1' input_file
<rss version=2.0>
<channel>
<title>Title string</title>
<link>https://domain/feed.xml</link>
<description>Description string here</description>
<language>en-us</language>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>Mon, 06 Dec 2021 00:00:00 +0000</pubDate>
</item>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>Mon, 06 Dec 2021 00:00:00 +0000</pubDate>
</item>
<item>
<title>title string here</title>
<link>link string with https style information</link>
<guid>link string with https style information</guid>
<pubDate>Mon, 06 Dec 2021 00:00:00 +0000</pubDate>
</item>
</channel>
</rss>
sed
如果设置了变量也可以使用
$ date="$(date +"%a, %d %b %Y %T %z")"
$ sed "/pubDate/ s/....-..-../$date/" input_file
如评论,一般情况下推荐使用xml解析工具。
如果 xml 文件与提供的示例完全对齐,bash
或 awk
可能在有限的条件下工作。
随着 bash:
#!/bin/bash
while IFS= read -r line; do
if [[ $line =~ (.*<pubDate>)([0-9]{4}-[0-9]{2}-[0-9]{2})(</pubDate>.*) ]]; then
datestr=$(date -d "${BASH_REMATCH[2]}" +"%a, %d %b %Y %T %z")
line="${BASH_REMATCH[1]}$datestr${BASH_REMATCH[3]}"
fi
echo "$line"
done < feed.xml
条件 $line =~ (.*<pubDate>)([0-9]{4}-[0-9]{2}-[0-9]{2})(</pubDate>.*)
匹配 <pubdate>
行分配 bash 变量 ${BASH_REMATCH[@]
带括号的子字符串。然后 line
使用重新格式化的日期字符串重建。
如果gawk
支持mktime()
和strftime()
功能,可以
也说 gawk
:
awk '
{
if (match([=11=], /^(.*<pubDate>)([0-9]{4})-([0-9]{2})-([0-9]{2})(<\/pubDate>.*)/, a) ) {
ts = mktime(a[2] " " a[3] " " a[4] " 00 00 00") # timestamp since the epoch
datestr = strftime("%a, %d %b %Y %T %z", ts)
[=11=] = a[1] datestr a[5]
}
} 1' feed.xml