将 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 文件与提供的示例完全对齐,bashawk 可能在有限的条件下工作。
随着 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