![如何根据模式连接多条线?](https://linux22.com/image/1263814/%E5%A6%82%E4%BD%95%E6%A0%B9%E6%8D%AE%E6%A8%A1%E5%BC%8F%E8%BF%9E%E6%8E%A5%E5%A4%9A%E6%9D%A1%E7%BA%BF%EF%BC%9F.png)
我想根据两行共享的模式将文件中的多行合并起来。
这是我的例子:
{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.}