Regex Unix模式日期时间匹配

Regex Unix模式日期时间匹配,regex,linux,unix,awk,sed,Regex,Linux,Unix,Awk,Sed,我想编辑这一行: 1987,4,12,31,4,1987-12-31 00:00:00.0000000,UA,19977,UA,,631,12197,1219701,31703,HPN,White Plains, NY,NY,36,New York,22,13930,1393001,30977,ORD,Chicago\, IL,IL,17,Illinois,41,756,802,483.2,6,6,0,0,0700-0759,,,,,914,938,600.8,24,24,1,1,0900-09

我想编辑这一行:

1987,4,12,31,4,1987-12-31 00:00:00.0000000,UA,19977,UA,,631,12197,1219701,31703,HPN,White Plains, NY,NY,36,New York,22,13930,1393001,30977,ORD,Chicago\, IL,IL,17,Illinois,41,756,802,483.2,6,6,0,0,0700-0759,,,,,914,938,600.8,24,24,1,1,0900-0959,0,,0,138,156,,1,738,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,US1NJBG0005,US1ILCK0027,,,,,,,,,,,,,1987-12-31 08:09:12.0000000,519494350
我希望输出是:

1987,4,12,31,4,1987-12-31 00:00:00.000,UA,19977,UA,63112197121970131703,HPN,White ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9494350

我想找到以下每种模式:
***-***-***-***:***:***:***:***.0000000

然后删除最后4个数字(0000),这样我就得到了
***-***-***-***:***:***:***:***.000.


如果该日期格式在第6列和第n-1列中有用,则可以使用以下格式获取第6列的值并删除最后四位:

awk-F'{print substr($6,0,length($6)-4)}'

类似地,N-1列可以通过以下方式达到:

awk-F'{print substr($(NF-1),0,length($(NF-1))-4}'

编辑:

$ echo '1987,4,12,31,4,1987-12-31 00:00:00.0000000,UA,19977,UA,,631,12197,1219701,31703,HPN,White Plains, NY,NY,36,New York,22,13930,1393001,30977,ORD,Chicago\, IL,IL,17,Illinois,41,756,802,483.2,6,6,0,0,0700-0759,,,,,914,938,600.8,24,24,1,1,0900-0959,0,,0,138,156,,1,738,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,US1NJBG0005,US1ILCK0027,,,,,,,,,,,,,1987-12-31 08:09:12.0000000,519494350' | sed -r 's/([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\....)..../\1/g'
1987,4,12,31,4,1987-12-31 00:00:00.000,UA,19977,UA,,631,12197,1219701,31703,HPN,White Plains, NY,NY,36,New York,22,13930,1393001,30977,ORD,Chicago\, IL,IL,17,Illinois,41,756,802,483.2,6,6,0,0,0700-0759,,,,,914,938,600.8,24,24,1,1,0900-0959,0,,0,138,156,,1,738,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,US1NJBG0005,US1ILCK0027,,,,,,,,,,,,,1987-12-31 08:09:12.000,519494350
要仅替换列中的值,但仍打印所有内容,请使用:

awk 'BEGIN{ FS=","; OFS=","} 
{ $6=substr($6, 0, length($6)-4); 
  $(NF-1)=substr( $(NF-1), 0,length($(NF-1))-4); 
  print $0}'
基于Awk的解决方案 格式良好的可移植脚本:

#/usr/bin/awk-f
开始{
FS=“,”#输入:字段之间用,
OFS=“,”#输出:字段之间用,
}
{
sub(/[0-9][0-9][0-9][0-9]$/,“”,$6)#从第6列中删除最后4位数字
sub(/[0-9][0-9][0-9][0-9]$/,“”,$(NF-1))#从n-1列中删除最后4位数字
打印
}
单线、不太便携的版本,使用:

N.B.传统的awk正则表达式引擎不支持
{N}
重复运算符,因此需要使用gawk版本3或更高版本运行。对于其他风格的awk,例如nawk,您需要像上面的可移植较长脚本一样显式重复正则表达式

基于sed的解决方案
sed-r的/^([^,]*,){5}([^,]+)[0-9]{4},([^,]*,)*([^,]+)[0-9]{4}(,[^,]*)$/\1\3\4\6\7/'

(通过测试)

这里有一个Perl解决方案

更新-编辑以输出完整的CSV行,时间戳替换为截断的

更新2-更新两个时间戳列,而不仅仅是第一个

#/usr/bin/env perl
严格使用;
使用警告;
使用特征“说”;
使用Text::CSV;
my$CSV=Text::CSV->new();
while(my$line=readline(STDIN)){
$CSV->parse($line)或die“无法解析行'$line'”;
我的@fields=$CSV->fields();
对于我的$f(@fields){
$f=~s/
^#字符串开头
(#开始捕获到1美元
\d{4}-#年
\d{2}-#月
\d{2}\s+#天
\d{2}:#小时
\d{2}:#分钟
\d{2}[.]#秒
\d{3}毫秒
)#结束捕获到1美元
\d{4}#不需要的亚秒精度
$#字符串末尾
/$1/gmsx;
}
$CSV->合并(@字段);
说$CSV->string();
}
例如:

alex@yuzu:~$ cat input.txt 
1987,4,12,31,4,1987-12-31 00:00:00.0000000,UA,19977,UA,,631,12197,1219701,31703,HPN,White Plains, NY,NY,36,New York,22,13930,1393001,30977,ORD,Chicago\, IL,IL,17,Illinois,41,756,802,483.2,6,6,0,0,0700-0759,,,,,914,938,600.8,24,24,1,1,0900-0959,0,,0,138,156,,1,738,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,US1NJBG0005,US1ILCK0027,,,,,,,,,,,,,1987-12-31 08:09:12.0000000,519494350

alex@yuzu:~$ ./csv.pl < input.txt
1987,4,12,31,4,"1987-12-31 00:00:00.000",UA,19977,UA,,631,12197,1219701,31703,HPN,"White Plains"," NY",NY,36,"New York",22,13930,1393001,30977,ORD,Chicago\," IL",IL,17,Illinois,41,756,802,483.2,6,6,0,0,0700-0759,,,,,914,938,600.8,24,24,1,1,0900-0959,0,,0,138,156,,1,738,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,US1NJBG0005,US1ILCK0027,,,,,,,,,,,,,"1987-12-31 08:09:12.000",519494350

你也可以试试这个GNU-sed命令

$ sed -r 's/^.*,([^,]*)....,.*$/\1/g' file
1987-12-31 08:09:12.000
如果你只想更换,那么试试这个

$ sed -r 's/^(.*,)([^,]*)....(,.*)$/\1\2\3/g' file
1987,4,12,31,4,1987-12-31 00:00:00.0000000,UA,19977,UA,,631,12197,1219701,31703,HPN,White Plains, NY,NY,36,New York,22,13930,1393001,30977,ORD,Chicago\, IL,IL,17,Illinois,41,756,802,483.2,6,6,0,0,0700-0759,,,,,914,938,600.8,24,24,1,1,0900-0959,0,,0,138,156,,1,738,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,US1NJBG0005,US1ILCK0027,,,,,,,,,,,,,1987-12-31 08:09:12.000,519494350
我想你希望输出是这样的

$ grep -oP '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\....' file
1987-12-31 00:00:00.000
1987-12-31 08:09:12.000
更新:

$ echo '1987,4,12,31,4,1987-12-31 00:00:00.0000000,UA,19977,UA,,631,12197,1219701,31703,HPN,White Plains, NY,NY,36,New York,22,13930,1393001,30977,ORD,Chicago\, IL,IL,17,Illinois,41,756,802,483.2,6,6,0,0,0700-0759,,,,,914,938,600.8,24,24,1,1,0900-0959,0,,0,138,156,,1,738,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,US1NJBG0005,US1ILCK0027,,,,,,,,,,,,,1987-12-31 08:09:12.0000000,519494350' | sed -r 's/([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\....)..../\1/g'
1987,4,12,31,4,1987-12-31 00:00:00.000,UA,19977,UA,,631,12197,1219701,31703,HPN,White Plains, NY,NY,36,New York,22,13930,1393001,30977,ORD,Chicago\, IL,IL,17,Illinois,41,756,802,483.2,6,6,0,0,0700-0759,,,,,914,938,600.8,24,24,1,1,0900-0959,0,,0,138,156,,1,738,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,US1NJBG0005,US1ILCK0027,,,,,,,,,,,,,1987-12-31 08:09:12.000,519494350

注意
I want
对于
问题来说不是一个好的格式。你试过什么?提示
awk-F','
和lookup
substr awk
是的,我尝试了所有方法,问题是我没有成功转到特定列,然后进行更改。我只在“1987-12-31 08:09:12.0000000”的文件上执行了awk“{sub(/…..$/,”)}1”,输出为1987-12-31 08:09:12.000。但是我可以在一个分隔的文本文件上做吗?对于这些类型的问题,找到你想要的文本总是很简单,但是排除你不想要的文本要困难得多。发布几行示例输入(包括您认为很难处理的任何情况)加上预期输出,或者您可能会得到一个解决方案,该解决方案适用于您发布的那一行,但在您的真实数据中对其他行无效。看,显然您正在尝试,但很简单-发布几行输入,而不仅仅是1,使用相关的预期输出,并确保两者的格式正确。不要紧,这是解决方案:awk--re interval-F,'{sub(“[0-9]{4}$”,“,$6”);sub([0-9]{4}$”,“,”,$(NF-1));for(i=1;icristian它看起来很棒!但我运行它并返回原始行。@user2783069,我刚刚重新运行了这两个版本,它们工作正常看看:awk-F,“{sub”([0-9]{4}$,”,“,$6);sub([0-9]{4}$,”,“,$(NF-1));for(i=1;该解决方案可能很好,它肯定会与OP提供的1行样本一起工作,但它实际上并没有实现OP所说的,即
我想找到的每个模式:***-***-***-***:***:***:***:***:***:***:***:***.0000000并擦除最后4位数字。因此如果
$6
$(NF-1)
可以包含与该模式不匹配但以4个零结尾的任何内容,那么OP会意外出现。顺便说一句,sub()的第一个参数是一个重复使用的重新分隔符(
/…/
而不是
“…”
)-它会根据重复解析的不同而有所不同)你可以说
print
,因为默认情况下它将
print$0
。@EdMorton,谢谢你的建议。至于脆弱性,被质疑者提到“如果这个日期格式在第6列和第n-1列中有用的话”.Hey!我如何运行此命令并同时打印其他列?但它只打印n-1列,我需要编辑整个文件。你知道如何操作吗?哦,你想用
1987-12-31 08:09:12.0000000
替换
1987-12-31 08:09:12.000
并保留其他列吗