ste*_*eve 2 bash text-processing
我有以下类型的表:
ID date DailyFlow
a 1972-01-01 17.0265761797993
b 1972-01-02 17.200476457399
c 1972-01-03 17.2926436045271
d 1972-01-04 17.3900277599829
e 1972-01-05 17.5987080931028
f 1972-01-06 17.6334881486229
g 1972-01-07 17.7030482596626
...
Run Code Online (Sandbox Code Playgroud)
我想将它们重新格式化如下:
YYYY DDD sim
1972 1 17.0265761797993
1972 2 17.200476457399
1972 3 17.2926436045271
1972 4 17.3900277599829
1972 5 17.5987080931028
1972 6 17.6334881486229
1972 7 17.7030482596626
1972 8 17.7204382874227
Run Code Online (Sandbox Code Playgroud)
第一行包含在表中。这些文件是带有“制表符”分隔符的纯文本 (*.txt)。ID 列是一个虚拟的列,我想摆脱它!在我想要的输出中,DDD 列上的数字 (1,2,3,...) 应与相应年份的日期相符。
有没有人知道如何做到这一点(使用 bash)?谢谢!
这本来是 的工作我最终得到了一个awk
,但第二列中的替换将需要gensub
,因此gawk
,默认情况下未安装,因此sed
解决方案:
sed -i.bak 's/[^\t]*\t\([^-]*\)-[0-9][0-9]-[0-9]\([0-9]\)[^\t]*\t\([^\t]*\)/\1\t\2\t\3/' infile
Run Code Online (Sandbox Code Playgroud)
或者,使用 ERE 缩短(感谢 user1598390):
sed -E -i.bak 's/.*([0-9]{4})-[0-9]{2}-([0-9]{2})(.*)/\1\t\2\3/' infile
Run Code Online (Sandbox Code Playgroud)
-i.bak
: 就地处理文件,将原始文件备份到 infile.bak
sed
命令分解:
s
:断言执行替换;/
: 开始模式[^\t]*
: 匹配任意数量的任意字符,不匹配\t
;\t
: 匹配一个\t
字符\(
: 开始第一个捕获组[^-]*
: 匹配任意数量的任意字符,不匹配-
;\)
: 停止第一个捕获组-
: 匹配一个-
字符[0-9]
: 匹配任何数字[0-9]
: 匹配任何数字-
: 匹配一个-
字符[0-9]
: 匹配任何数字\(
: 启动第二个捕获组[0-9]
: 匹配任何数字\)
: 停止第二个捕获组[^\t]*
: 匹配任意数量的任意字符,不匹配\t
;\t
: 匹配一个\t
字符\(
: 启动第三个捕获组[^\t]*
: 匹配任意数量的任意字符,不匹配\t
;\)
: 停止第三个捕获组/
: 停止模式/开始替换字符串\1
: 反向引用替换为第一个捕获组\2
: 反向引用替换为第二个捕获组\3
: 反向引用替换为第三个捕获组/
: 停止替换字符串/启动修饰符示例文件的输出:
user@debian ~/tmp % cat infile
a 1972-01-01 17.0265761797993
b 1972-01-02 17.200476457399
c 1972-01-03 17.2926436045271
d 1972-01-04 17.3900277599829
e 1972-01-05 17.5987080931028
f 1972-01-06 17.6334881486229
g 1972-01-07 17.7030482596626
user@debian ~/tmp % sed 's/[^\t]*\t\([^-]*\)-[0-9][0-9]-[0-9]\([0-9]\)[^\t]*\t\([^\t]*\)/\1\t\2\t\3/' infile
1972 1 17.0265761797993
1972 2 17.200476457399
1972 3 17.2926436045271
1972 4 17.3900277599829
1972 5 17.5987080931028
1972 6 17.6334881486229
1972 7 17.7030482596626
Run Code Online (Sandbox Code Playgroud)