sed仅搜索和替换特定列

sed仅搜索和替换特定列,sed,Sed,我从wunderground.com和我一起获取天气日,然后整理数据,以便在gnuplot上使用。我很难将第二列数据从数字缩写替换为月份缩写。只对第二列感兴趣 我想从这开始 >2013 08 02 23 37 00 73.3 >2013 08 02 23 42 00 73.4 >2013 08 02 23 45 00 73.3 >2013 08 02 23 47 00 73.1 >2013 08 02 23 52 00 73.1 >2013 08 02 23

我从wunderground.com和我一起获取天气日,然后整理数据,以便在gnuplot上使用。我很难将第二列数据从数字缩写替换为月份缩写。只对第二列感兴趣

我想从这开始

>2013 08 02 23 37 00 73.3
>2013 08 02 23 42 00 73.4
>2013 08 02 23 45 00 73.3
>2013 08 02 23 47 00 73.1
>2013 08 02 23 52 00 73.1
>2013 08 02 23 57 00 73.1
为此:

>2013 AUG 02 23 37 00 73.3
>2013 AUG 02 23 42 00 73.4
>2013 AUG 02 23 45 00 73.3
>2013 AUG 02 23 47 00 73.1
>2013 AUG 02 23 52 00 73.1
>2013 AUG 02 23 57 00 73.1
我正在尝试使用sed将数字转换为正确的月份,我一直在得到这个结果。我只希望正确的sed表达式执行它们,而不是全部执行。这是我试图使用的命令

sed -e 's/01/JAN/' -e 's/02/FEB/' -e 's/03/MAR/' -e 's/04/APR/' -e 's/05/MAY/' -e 's/06/JUN/' -e 's/07/JUL/' -e 's/08/AUG/' -e 's/09/SEP/' -e 's/10/OCT/' -e 's/11/NOV/' -e 's/12/DEC/'

我该如何处理这个问题。

解决这个问题的方法,因为您的第一列内容是非常可预测的,但不是一般性的问题:

sed -E -e 's/^([0-9]{4}) 01/\1 JAN/' -e 's/^([0-9]{4}) 02/\1 FEB/' etc.
awk有一个子功能,对于这里的许多选项来说,它可能会变得笨拙


Perl脚本可能是最好的方法。

解决此问题的变通方法,因为您的第一列内容是非常可预测的,但不是一般问题:

sed -E -e 's/^([0-9]{4}) 01/\1 JAN/' -e 's/^([0-9]{4}) 02/\1 FEB/' etc.
awk有一个子功能,对于这里的许多选项来说,它可能会变得笨拙

Perl脚本可能是最好的方法。

我将使用awk来实现这一点:

$ awk 'BEGIN{split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",a)} {$2=a[$2+0]}1' a
>2013 Aug 02 23 37 00 73.3
>2013 Aug 02 23 42 00 73.4
>2013 Aug 02 23 45 00 73.3
>2013 Aug 02 23 47 00 73.1
>2013 Aug 02 23 52 00 73.1
>2013 Aug 02 23 57 00 73.1
要使用新内容更新字段,只需重定向,然后移动:

awk .... file > temp_file && mv temp_file file
解释 我们要做的是给awk一个包含月份名称的字符串列表。一旦我们把它转换成一个数组,a[1]将是一月,a[2]二月,依此类推。因此,这只是将第二个字段替换为[2nd field]的问题

开始{splitJan二月三月四月五月六月七月八月九月十月十一月十二月,a}获取数据并插入a[]数组。 {$2=a[$2+0]}将第二个字段设置为[2nd field]。$2+0用于将08转换为8。 最后,1的计算结果为true,并使awk执行其默认操作:{print$0}。 我会使用awk来实现这一点:

$ awk 'BEGIN{split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",a)} {$2=a[$2+0]}1' a
>2013 Aug 02 23 37 00 73.3
>2013 Aug 02 23 42 00 73.4
>2013 Aug 02 23 45 00 73.3
>2013 Aug 02 23 47 00 73.1
>2013 Aug 02 23 52 00 73.1
>2013 Aug 02 23 57 00 73.1
要使用新内容更新字段,只需重定向,然后移动:

awk .... file > temp_file && mv temp_file file
解释 我们要做的是给awk一个包含月份名称的字符串列表。一旦我们把它转换成一个数组,a[1]将是一月,a[2]二月,依此类推。因此,这只是将第二个字段替换为[2nd field]的问题

开始{splitJan二月三月四月五月六月七月八月九月十月十一月十二月,a}获取数据并插入a[]数组。 {$2=a[$2+0]}将第二个字段设置为[2nd field]。$2+0用于将08转换为8。 最后,1的计算结果为true,并使awk执行其默认操作:{print$0}。
这可能适用于GNU sed:

sed -nri 'G;s/$/01JAN02FEB03MAR04APR05MAY06JUN07JUL08AUG09SEP10OCT11NOV12DEC/;s/ (..)(.*)\1(...)/ \3\2/;P' file

这会在每行末尾添加一个查找表,并用键替换值。

这可能适用于GNU-sed:

sed -nri 'G;s/$/01JAN02FEB03MAR04APR05MAY06JUN07JUL08AUG09SEP10OCT11NOV12DEC/;s/ (..)(.*)\1(...)/ \3\2/;P' file

这将在每行的末尾添加一个查找表,并用键替换值。

使用gnu awk的函数strftime和mktime

awk '{$2=strftime("%b",mktime("2014 " $2 " 1 1 0 0"))}1' file

>2013 Aug 02 23 37 00 73.3
>2013 Aug 02 23 42 00 73.4
>2013 Aug 02 23 45 00 73.3
>2013 Aug 02 23 47 00 73.1
>2013 Aug 02 23 52 00 73.1
>2013 Aug 02 23 57 00 73.1
解释 mktime2014$2 11 0 0假大纪元时间,将第2列用作月份 strftime%b,mktime2014$2 1 10 0将历元转换回日期,使用%b导出缩写的月份名称Jan、Feb等 此awk的好处是: 当然,它比较短。其次,您可以在strftime中控制/调整格式,以导出您喜欢的任何日期格式

例如,如果更改为完整月份名称%B,则无需重写代码

awk '{$2=strftime("%B",mktime("2014 " $2 " 1 1 0 0"))}1' file

使用gnu awk的函数strftime和mktime

awk '{$2=strftime("%b",mktime("2014 " $2 " 1 1 0 0"))}1' file

>2013 Aug 02 23 37 00 73.3
>2013 Aug 02 23 42 00 73.4
>2013 Aug 02 23 45 00 73.3
>2013 Aug 02 23 47 00 73.1
>2013 Aug 02 23 52 00 73.1
>2013 Aug 02 23 57 00 73.1
解释 mktime2014$2 11 0 0假大纪元时间,将第2列用作月份 strftime%b,mktime2014$2 1 10 0将历元转换回日期,使用%b导出缩写的月份名称Jan、Feb等 此awk的好处是: 当然,它比较短。其次,您可以在strftime中控制/调整格式,以导出您喜欢的任何日期格式

例如,如果更改为完整月份名称%B,则无需重写代码

awk '{$2=strftime("%B",mktime("2014 " $2 " 1 1 0 0"))}1' file
因为它出现在评论中:

将月号映射到名称的惯用awk方法是:

number = (match("JanFebMarAprMayJunJulAugSepOctNovDec",<name>)+2)/3
请注意,无论转换是从哪个方向进行的,脚本都会在几个月内使用相同的定义,并且在两个方向上都是类似的数学计算

当然,这样做也没什么错:

awk 'BEGIN{

    split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",num2name)

    for (number in num2name) {
        name2num[num2name[number]] = number
    }

    name = "Jul"

    number = name2num[name]

    print name " -> " number

    name = num2name[number]

    print number " -> " name

}'
Jul -> 7
7 -> Jul
再多写几行代码,nbd

因为它出现在评论中:

将月号映射到名称的惯用awk方法是:

number = (match("JanFebMarAprMayJunJulAugSepOctNovDec",<name>)+2)/3
请注意,无论转换是从哪个方向进行的,脚本都会在几个月内使用相同的定义,并且在两个方向上都是类似的数学计算

当然,这样做也没什么错:

awk 'BEGIN{

    split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",num2name)

    for (number in num2name) {
        name2num[num2name[number]] = number
    }

    name = "Jul"

    number = name2num[name]

    print name " -> " number

    name = num2name[number]

    print number " -> " name

}'
Jul -> 7
7 -> Jul

只需再写几行代码,nbd。

谢谢您的快速响应!你能更详细地解释一下awk系列吗?工作得很有魅力!谢谢你可以把所有的都放在一个地方,用开始部分来定义months@BMW是对的,但是你甚至不需要月变量,你也不需要;不需要第三个参数进行拆分,因为这是默认值。你所需要的就是拆分1月2月3月4月5月6月7月8月9月10月11月12日。谢谢@EdMorton,我不知道拆分的默认值。更新。感谢您的快速响应!你能更详细地解释一下awk系列吗?工作得很有魅力!谢谢你可以把所有的都放在一个地方,用开始部分来定义months@BMW是对的,但你甚至不需要
月份是可变的,你不知道;不需要第三个参数进行拆分,因为这是默认值。你所需要的就是拆分1月2月3月4月5月6月7月8月9月10月11月12日。谢谢@EdMorton,我不知道拆分的默认值。更新。@BMW我不相信此方法请参见。感谢共享url。@BMW我不相信此方法请参见。感谢共享url。您应该说明解决方案何时是GNU awk特定的解决方案,例如此解决方案,以便使用非GNU awk尝试此解决方案的人不会浪费时间试图找出它不适用于他们的原因。在这些情况下,我也会特别使用命令名gawk,只是为了明确它是特定于gawk的。您应该说明解决方案何时是特定于GNU awk的,就像这样,这样使用非GNU awk的人就不会浪费时间试图弄清楚为什么它对他们不起作用。在这些情况下,我也会特别使用命令名gawk,只是为了明确它是特定于gawk的。Thsi非常机智!我还认为,如果您想使用它,它将不会有太大的变化,例如,您想使用它只是习惯用法的awk代码的自然反转来将日期名称映射到它的编号:awk“BEGIN{print matchJanFebMarAprMayJunJulAugSepOctNovDec,Aug+2/3}”->8。对称性是好软件的一个重要组成部分——谷歌QWAN没有名字的质量。这是非常鼓舞人心的,非常好的东西。我下载了一篇论文。它与反函数的数学概念密切相关。当然,并不总是可以拥有它们,但它看起来是一种很好的编码方式。当然还有+1。是的,这看起来是一个很好的起点。所有这些图案都出自建筑师克里斯托弗·亚历山大(Christopher Alexander)之手,他在世界各地试图找出是什么让一些建筑和人等变得美丽,他给出的答案是对称。为一般认为美丽的人/事拍照,在他们的脸、眼睛、耳朵等之间画垂直和水平线,然后他们会排成一行。可测量的好软件也有对称的美,所以如果你写对称的软件,它比不对称的软件有更好的机会成为好软件。Thsi非常机智!我还认为,如果您想使用它,它将不会有太大的变化,例如,您想使用它只是习惯用法的awk代码的自然反转来将日期名称映射到它的编号:awk“BEGIN{print matchJanFebMarAprMayJunJulAugSepOctNovDec,Aug+2/3}”->8。对称性是好软件的一个重要组成部分——谷歌QWAN没有名字的质量。这是非常鼓舞人心的,非常好的东西。我下载了一篇论文。它与反函数的数学概念密切相关。当然,并不总是可以拥有它们,但它看起来是一种很好的编码方式。当然还有+1。是的,这看起来是一个很好的起点。所有这些图案都出自建筑师克里斯托弗·亚历山大(Christopher Alexander)之手,他在世界各地试图找出是什么让一些建筑和人等变得美丽,他给出的答案是对称。为一般认为美丽的人/事拍照,在他们的脸、眼睛、耳朵等之间画垂直和水平线,然后他们会排成一行。可测量的好软件也有对称的美,所以如果你写对称的软件,它比不对称的软件有更好的机会成为好软件。