分支周期结束后执行一些正则表达式

时间:2018-08-09 08:41:48

标签: sed

我有一个文件,其日期用制表符和换行符分隔:

20171113T090319Z    20171120T125820Z    20171214T082222Z
20171213T074023Z    20171229T070931Z    20171115T112126Z
20171212T075236Z    20171212T121328Z    20171024T084925Z
20171024T171827Z    20171115T120126Z    20171218T093732Z
20171027T065928Z    20171212T133230Z    20171212T085634Z
20171219T162619Z    20171109T142727Z    20171114T145032Z

我需要以这种方式转换此文件。将其设置为一行,并在每个日期之前添加一些文本:

imageTag=20171113T090319Z imageTag=20171120T125820Z imageTag=20171214T082222Z imageTag=20171218T125131Z imageTag=20171017T141829Z imageTag=20171127T160931Z

我是sed和其他工具的新手,这就是为什么我要为丑陋的代码表示歉意

第一种方法只是使用单独的sed命令进行转换:

 cat test.txt |
 sed 's/\t/\n/g' |
 sed 's/^/imageTag=/g' |
 sed -e ':a;N;$!ba;s/\n/ /g'

然后我决定将其重写为单个sed:

cat test.txt | sed -e ':x;N;s/[\t\n]/ imageTag=/g;bx; s/^/imageTag=/' 

但是在此示例中,s/^/imageTag=/的最后一部分从未执行。

所以我的问题是:bx;之后如何执行代码(无条件分支)

我以cat test.txt | sed -e ':x;N;s/[\t\n]/ imageTag=/g;/^imageTag/! s/^/imageTag=/;bx;'的方式重写了它。但这只是解决方法。

2 个答案:

答案 0 :(得分:2)

这可能对您有用(GNU sed):

sed 'y/\t/\n/;s/^/imageTag=/Mg;1h;1!H;$!d;x;y/\n/ /' file

将每个选项卡转换为换行符。在每行的开头插入所需的字符串(替代命令中的M标志调用多行模式,该模式允许在正则表达式中使用^$来表示行的开始/结束);将每行收集到保留空间中,并在文件末尾将每条换行符转换为一个空格。

答案 1 :(得分:1)

您的脚本看起来异常复杂。如果您的sed可以识别\t的制表符和\n的换行符,请尝试

sed 's/\(^\|\t\|\n\)/ imageTag=/g;s/^ //;s/ imageTag=$//' test.txt

最后两个命令是处理行首和行尾的简单修正。我确信首先可以避免使用它们,但这似乎很简单。

还请注意我们如何避免难看的useless use of cat.

正如评论所见证的那样,这并不是很容易移植。也许更喜欢定义更明确的工具。

perl -0777 -pe 's/(^|\t|\n)/ imageTag=/g;s/^ //;s/ imageTag=$//' test.txt

-0777“暂存模式”会将整个文件读入内存,因此,如果输入为数GB,则不要执行此操作。

具有讽刺意味的是,sed是由POSIX标准化的,而Perl没有正式的规范。但是由于只有Perl的一种实现,并且POSIX无法在sed中准确地指定许多内容,因此,事实上最终结果是Perl比sed具有更高的可移植性。