我想yyyy-mm-dd hh:mm:ss
从下面的文件中删除除第一个之外的所有出现的内容。所以基本上我希望显示该行的第一次出现,并且我希望删除所有剩余的重复行。有人可以帮助我使用正则表达式 cmd 来做到这一点吗?
Will use per-minute statistics
Stats from 2016-06-26 00:00:00 to 2016-06-26 23:59:00
yyyy-mm-dd hh:mm:ss
6/26/2016 0:01:00
6/26/2016 0:03:00
yyyy-mm-dd hh:mm:ss
6/26/2016 0:01:00
yyyy-mm-dd hh:mm:ss
6/26/2016 0:01:00
6/26/2016 0:02:00
6/26/2016 0:03:00
答案1
如果您只想删除所有重复的 yyyy-mm-dd 行,那么
% sed '/^yyyy-mm-dd/,$ { n ; /^yyyy-mm-dd/d }' srcfile
Will use per-minute statistics
Stats from 2016-06-26 00:00:00 to 2016-06-26 23:59:00
yyyy-mm-dd hh:mm:ss
6/26/2016 0:01:00
6/26/2016 0:03:00
6/26/2016 0:01:00
6/26/2016 0:01:00
6/26/2016 0:02:00
6/26/2016 0:03:00
如果你想删除所有重复的行,那么这有点hack'n'slashy并且效率低下,但是有效并且很容易理解。 (您可以优化第二个 sed | grep,但这样更容易阅读,恕我直言)。
% sed -n '1,/^yyyy-mm-dd/p' srcfile ; sed '1,/^yyyy-mm-dd/d' srcfile | grep -v ^yyyy-mm-dd | sort -u
Will use per-minute statistics
Stats from 2016-06-26 00:00:00 to 2016-06-26 23:59:00
yyyy-mm-dd hh:mm:ss
6/26/2016 0:01:00
6/26/2016 0:02:00
6/26/2016 0:03:00
答案2
正确的工具是 awk。它可以让您以简单的方式表达逻辑:seen
第一次看到模式时设置一个变量,如果已经看到模式,则跳过与模式匹配的行。如果没有跳过一行,则打印它。
awk '/^yyyy-mm-dd[ \t]+hh:mm:ss$/ {if (seen) next; ++seen}
1 {print}'
这可以缩写,但会变得更加神秘。
awk '!(/^yyyy-mm-dd[ \t]+hh:mm:ss$/ && !(seen++))'
答案3
sed -e '0,/^yyyy-mm-dd\s\+hh:mm:ss$/!{/^yyyy-mm-dd\s\+hh:mm:ss$/d}'
(GNU sed 功能)范围0,/pattern/
匹配到第一次出现,因此在文件的其余部分0,/pattern/!
运行 的内容,删除所有后面的匹配项。{...}
答案4
GNU支持正则表达式地址的数字偏移,因此您可以寻址从到文件末尾的ed
范围。然后,您可以删除与该范围内的相同正则表达式匹配的任何行。最后写入修改后的文件并退出。 /pattern/+1
$
g//d
ed file << EOF
/^yyyy-mm-dd/+1,$ g//d
wq
EOF
或同等地
printf '/^yyyy-mm-dd/+1,$ g//d\nwq\n' | ed file