在bash中提取子字符串的字典?

时间:2015-02-25 10:32:41

标签: regex bash

我有类似的文件:

(1), (2), (3), (4), (5), (6), (10), (11), (12), (13), (14), (15), (16), (17), (18), (24), (25), (26), (27), (28), (29), (30), (31), (32), (33), (34), (35), (36), (37), (38), (39), (40), (41), (42), (43), (51), (52), (53), (54), (55), (56), (57), (58), (62), (63), (64), (65), (66), (67), (68), (69), (70), (71), (72), (73), (74) Use method number 1. (7), (8), (9), (19), (20), (21), (22), (23), (59), (60), (61) Use method number 2. (44), (45), (46), (47), (48), (49), (50) Use method number 3.

我想建立一个包含括号之间数字的字典,并将它们链接到类型的句子:“Use method number #”。所以,在这种情况下:

1,2,3,4,5...74 --> Use method number 1.
7,8,9,19....61 --> Use method number 2.

目前我正在构建一个复合体,同时读取正则表达式(^ *\([0-9]+\)),提取每个数字,删除巧合并重新开始直到找不到正则表达式,然后提取句子。但这在性能上相当差,而且维护起来很乏味。

关于如何通过while do之外的更紧凑的方法来改进这一点,您有什么建议吗?

我没有受到字典结构的困扰,如果不暗示修改方法,请不要立即考虑。

修改。添加实际数据字符串:

(12),(13),(14),(15)P.S。:3díasencultivo de invernadero。 Efectuarunmáximode6 aplicaciones por                        Campañaaintervalos de7díasutilizandounvolumenmáximodecaldo de 600 l / Ha。 yunmáximode                        7,5 Kg decobreinorgánicoepremporña。                        (28)Tratamientoenotoño,pulverizando hasta una altura de 1,5 m。                        (44),(45),(46),(47),(48),(49),(50),(51)Efectuarsólotratamientosdesde la cosecha hasta la                        floración,limitandolaaplicación一个1200升。德卡尔多/哈。 yunmáximode3 aplicaciones porCampaña                        (con un intervalo de tratamientos de14días)yunmáximode7,5 Kg。 decobreinorgánico/ Ha.por                        坎帕纳。

3 个答案:

答案 0 :(得分:1)

相当惯用的gnu awk解决方案:

awk -v RS="Use method number [0-9]."
    -v OFS=" --> "
    'NF{gsub(/\s*|\(|\)/, ""); print $0, RT}' file

测试

$ awk -v RS="Use method number [0-9]." -v OFS=" --> " 'NF{gsub(/\s*|\(|\)/, ""); print $0, RT}' a
1,2,3,4,5,6,10,11,12,13,14,15,16,17,18,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,51,52,53,54,55,56,57,58,62,63,64,65,66,67,68,69,70,71,72,73,74 --> Use method number 1.
7,8,9,19,20,21,22,23,59,60,61 --> Use method number 2.
44,45,46,47,48,49,50 --> Use method number 3.

解释

  • -v RS="Use method number [0-9]."将记录分隔符设置为字符串“使用方法编号X。,X为数字。
  • -v OFS=" --> "设置打印分隔符。
  • NF{gsub(/\s*|\(|\)/, ""); print $0, RT}主要代码 - NF {}如果至少有一个字段,请继续。 - gsub(/\s*|\(|\)/, "")从字符串中删除所有空格()。 - print $0, RT将替换的字符串与使用的记录分隔符一起打印(“使用方法编号X”。)。使用RT代替RS,以便我们捕获字符串中使用的特定X的值。

来自man awk

  

<强> RT

     

记录终止符。 Gawk将RT设置为匹配的输入文本   RS指定的字符或正则表达式。

答案 1 :(得分:1)

您可以使用sed

sed -r 's/( *\(|\))//g;s/\./\n/g' input.txt

这假定您的输入文件不包含换行符。如果它包含换行符,则需要对命令进行一些修改。

<强>解释

第一个命令s/( *\(|\))//g删除括号和其他空格。第二个命令s/\./\n/g在点后添加换行符。


哦,我错过了你想要添加额外的-->。如果你真的需要,第二个sed命令需要修改:

sed -r 's/( *\(|\))//g;s/U[^.]+\./--> \0\n/g' input.txt

现在,第二个命令搜索序列U --> until a dot,并预先添加-->加上点后添加换行符。

<强>输出:

1,2,3,4,5,6,10,...,74 --> Use method number 1.
7,8,9,19,20,21,22,23,59,60,61 --> Use method number 2.
44,45,46,47,48,49,50 --> Use method number 3.

另一件事:上面的命令在输出结尾添加了一个额外的换行符。您可以通过添加第三个sed命令s/\n$//来抑制它,该命令会在输出结束之前删除其他新行:

sed -r 's/( *\(|\))//g;s/U[^.]+\./--> \0\n/g;s/\n$//' input.txt

答案 2 :(得分:1)

您可以非常直观地使用ed脚本

进行操作
:: ed.script ::
# first you split your data in multiple lines
,s/\(\(([0-9]*), \)*([0-9]*)\)/\
\1\
/g

# then for each matching line with numbers, you remove unwanted chars
# and append " --> " to the next line
,g/\(\(([0-9]*), \)*([0-9]*)\)/\
s/[)( ]//g\
a\
 -->\
.

# and finally you join lines
,g/^ -->/-1,+1j

# save if you want
w

然后使用以下命令启动它:

cat ed.script | ed -s file.txt

这是直观的部分......它适用于您的样本数据。