我有一个文件,其日期用制表符和换行符分隔:
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;'
的方式重写了它。但这只是解决方法。
答案 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
具有更高的可移植性。