我有一个格式为的文本文件:
aaa: bcd;bcd;bcddd;aaa:bcd;bcd;bcd;
“bcd”可以是任何字符的任意长度,不包括;
或:
我想要做的是以下列格式打印文本文件:
aaa: bcd;bcd;bcddd;
aaa: bcd;bcd;bcd;
-etc -
我解决此问题的方法是隔离“;...:
”模式,然后在没有初始;
我总结说我必须使用awk的'gsub'才能做到这一点,但不知道如何复制模式,也不知道如何在我的模式中添加新行字符1字符再次打印模式。
这可能吗? 如果没有,你能指导我解决它吗?
答案 0 :(得分:1)
我们无法确定aaa
或bcd
部分的可变性;据推测,每个人几乎都可以。
您可能应该寻找:
这构成了你想要匹配的单位。
/[^:;]+:([^:;]+;)+/
使用它,您可以替换相同的内容后跟换行符,然后打印结果。唯一的技巧是避免多余的换行。
{
echo "aaa: bcd;bcd;bcddd;aaa:bcd;bcd;bcd;"
echo "aaz: xcd;ycd;bczdd;baa:bed;bid;bud;"
} |
awk '{ gsub(/[^:;]+:([^:;]+;)+/, "&\n"); sub(/\n+$/, ""); print }'
aaa: bcd;bcd;bcddd;
aaa:bcd;bcd;bcd;
aaz: xcd;ycd;bczdd;
baa:bed;bid;bud;
在评论中解释问题:
为什么正则表达式不包括冒号之前的字符(这是它打算做的,但我不明白为什么)?我不明白"休息"或结束正则表达式。
当我试图在顶部解释时,你正在寻找我们可以称之为'单词',这意味着既不是冒号也不是分号的字符序列。在正则表达式中,即[^:;]+
,表示一个或多个(+
)否定字符类 - 一个或多个非冒号,非分号字符。
让我们假装正则表达式中的空格不重要。我们可以像这样填充正则表达式:
/ [^:;]+ : ( [^:;]+ ; ) + /
当然,斜线只标记两端。第一个集群是一个单词;然后有一个冒号。然后有一个括在括号中的组,最后用+
标记。这意味着该组的内容必须至少发生一次,并且可能发生的次数超过该次数。小组里面有什么?好吧,一个单词后面跟着一个分号。它不必每次都是同一个词,但那里必须有一个词。如果某些事情可能发生零次或多次,那么当然使用*
代替+
。
正则表达式停止的关键是第一行中间的aaa:
不是由一个单词后面跟一个分号组成的;它是一个单词后跟冒号。因此,正则表达式必须在此之前停止,因为aaa:
与该组不匹配。因此,gsub()
找到第一个序列,并用相同的材料和换行符替换该文本(当然,"&\n"
也是如此)。它(gsub()
)然后在替换材料结束后直接恢复其搜索,并且 - 看,有一个单词后面跟冒号,一些单词后跟分号,所以第二个匹配用原始材料和换行符替换。
我认为$0
必须在该行末尾包含换行符。因此,如果没有sub()
删除尾随换行符,则print
(隐含$0
换行)会在输出中生成一条我不想要的空白行,所以我删除了无关的换行符。 $0
末尾的换行符不会与gsub()
匹配,因为它后面没有冒号或分号。
答案 1 :(得分:1)
这可能对您有用:
awk '{gsub(/[^;:]*:/,"\n&");sub(/^\n/,"");gsub(/: */,": ")}1' file
\n
)添加到不包含;
或:
后跟:
:
替换为:
,后跟任意一个空格,后跟一个空格。或者这个:
sed 's/;\([^;:]*: *\)/;\n\1 /g' file
答案 2 :(得分:0)
不确定如何在awk中执行此操作,但是使用sed可以实现我想要的功能:
$ nl='
'
$ sed "s/\([^;]*:\)/\\${nl}\1/g" input
第一个命令将shell变量$ nl设置为包含单个新行的字符串。某些版本的sed允许您在替换字符串中使用\ n,但并非所有版本都允许。这样可以保留最终后出现的任何空格;并把它放在行的开头。要摆脱它,你可以做到
$ sed "s/\([^;]*:\)/\\${nl}\1/g; s/\n */\\$nl/g" input
答案 3 :(得分:0)
普通的awk gsub()和sub()不允许你在替换字符串中指定组件Gnu awk - “gawk” - 提供“gensub()”,这将允许“gensub(/(;)(。+ :)/, “\ 1 \ n \ 2”, “G”)“