如何根据模式连接多条线?

如何根据模式连接多条线?

我想根据两行共享的模式将文件中的多行合并起来。

这是我的例子:

{101}{}{Apples}
{102}{}{Eggs}
{103}{}{Beans}
{104}...
...

{1101}{}{This is a fruit.}
{1102}{}{These things are oval.}
{1103}{}{You have to roast them.}
{1104}...
...

我想加入{101}{}{Apples}队伍{1101}{}{This is a fruit.}

集中到一行{101}{}{Apples}{1101}{}{This is a fruit.}进行进一步处理。

其它线路也同样如此。

如您所见,两条线都共用数字 101,但我不知道如何实现这一点。有什么想法吗?

/编辑:

我找到了一个“解决方法”:

C-V首先,在 VISUAL BLOCK 模式下用(或类似的快捷方式)从第二组中删除所有前面的“{1”字符,然后使用 按数字对所有行进行排序:%sort n,然后用 连接每隔一行,然后:let @q = "Jj"跟上500@q

这有效,但留下了{101}{}{Apples} 101}{}{This is a fruit.}。然后我需要在每一行中添加缺失的字符“{1”,这不是我想要的。任何帮助表示感谢。

答案1

不用删除{1,只需执行

:%sort rn /\d\d\d}/

这将进行数字排序,但在每一行上它只会查看后跟 } 的三个数字。

另外,为了随后加入队伍,我会这样做

:g/{\d\d\d}/j!

答案2

以下是在 shell 中使用文件执行此操作的方法:

join -j 2 \
    <(sed -n '/^{...}/{s/{/{ /;s/}/ }/;p}' inputfile) \
    <(sed -n '/^{....}/{s/{./& /;s/}/ }/;p}' inputfile) |
    sed 's/^\([^ ]*\) { }{}\({[^}]*}\) {1 }\({.*}\)$/{\1}{}\2{1\1}\3/'

它使用前两次调用来sed根据第一组花括号之间的数字数量拆分文件,并在最后三位数字周围添加空格({101}become{ 101 }{1101}become {1 101 })。然后,它使用这三位数作为join命令 key on 的字段。最后一个sed命令将数字放回原位,并删除先前添加的额外空格。

专家vim可能会在 中做得更好vim。我可以使用 AWK 做一些比上述更直接的事情。

答案3

下面是使用命令行中的 Vim/Ex 编辑器处理一个模式的示例:

$ ex +'redir @a|sil g/101}/' +'redi>>/dev/stdout|echon join(split(@a),"")' -scq! input.txt 
{101}{}{Apples}{1101}{}{This is a fruit.}

对于多个模式,可以使用额外的命令重复,添加循环,或者从 shell 循环,例如

$ for i in `seq 1 3`; do ex +"redir @a|sil g/10$i}/" +'redi>>/dev/stdout|echo join(split(@a),"")' -scq! input.txt; done
{101}{}{Apples}{1101}{}{Thisisafruit.}
{102}{}{Eggs}{1102}{}{Thesethingsareoval.}
{103}{}{Beans}{1103}{}{Youhavetoroastthem.}

仅使用 shell 来解析数据,就简单得多,例如:

$ grep "101}" input.txt | xargs
{101}{}{Apples} {1101}{}{This is a fruit.}

对于多行:

$ for i in `seq 1 4`; do grep "10$i}" input.txt | xargs; done
{101}{}{Apples} {1101}{}{This is a fruit.}
{102}{}{Eggs} {1102}{}{These things are oval.}
{103}{}{Beans} {1103}{}{You have to roast them.}

相关内容