使用各种分隔符

时间:2015-08-14 08:03:01

标签: python awk sed grep

我的文本文件(不幸的是)看起来像这样......

<amar>[amar-1000#Fem$$$_Y](1){india|1000#Fem$$$,mumbai|1000#Mas$$$}
<akbar>[akbar-1000#Fem$$$_Y](1){}
<john>[-0000#$$$_N](0){USA|0100#$avi$$,NJ|0100#$avi$$}

它包含客户名称,后跟一些信息。顺序是......

文本字符串后跟list,set然后是字典

&LT;&GT; [](){}

这不是python兼容文件,因此数据不符合预期。我想处理文件并提取一些信息。

amar 1000 | 1000  | 1000
akbar 1000  
john 0000  | 0100 | 0100

1)&lt;&gt;

之间的名称

2)列表中的 - 和#之间的数字

3&amp; 4)用逗号分隔字典和|之间的数字和#(这里可以有两个以上的条目)

我愿意使用最适合此任务的任何工具。

4 个答案:

答案 0 :(得分:3)

由于语法非常复杂,您可能会找到一个合适的解析器作为最佳解决方案。

#!/usr/bin/env python

import fileinput
from pyparsing import Word, Regex, Optional, Suppress, ZeroOrMore, alphas, nums


name = Suppress('<') + Word(alphas) + Suppress('>')
reclist = Suppress('[' + Optional(Word(alphas)) + '-') + Word(nums) + Suppress(Regex("[^]]+]"))
digit = Suppress('(' + Word(nums) + ')')
dictStart = Suppress('{')
dictVals = Suppress(Word(alphas) + '|') + Word(nums) + Suppress('#' + Regex('[^,}]+') + Optional(','))
dictEnd = Suppress('}')

parser = name + reclist + digit + dictStart + ZeroOrMore(dictVals) + dictEnd

for line in fileinput.input():
    print ' | '.join(parser.parseString(line))

此解决方案使用pyparsing库并运行产生:

$ python parse.py file
amar | 1000 | 1000 | 1000
akbar | 1000
john | 0000 | 0100 | 0100

答案 1 :(得分:2)

您可以将所有分隔符添加到中的FS变量并计算字段,例如:

awk -F'[<>#|-]' '{ print $2, $4, $6, $8 }' infile

如果大括号之间有两个以上的条目,您可以使用循环遍历所有字段,直到最后一个,如:

awk -F'[<>#|-]' '{ 
    printf "%s %s ", $2, $4
    for (i = 6; i <= NF; i += 2) { 
        printf "%s ", $i 
    }
    printf "\n" 
}' infile

两个命令产生相同的结果:

amar 1000 1000 1000 
akbar 1000 
john 0000 0100 0100

答案 2 :(得分:2)

您可以使用正则表达式来捕获参数

<强>样品:

a="<john>[-0000#$$$_N](0){USA|0100#$avi$$,NJ|0100#$avi$$}"
name=" ".join(re.findall("<(\w+)>[\s\S]+?-(\d+)#",a)[0])
others=re.findall("\|(\d+)#",a)
print name+" | "+" | ".join(others) if others else " "

<强>输出:

'john 0000 | 0100 | 0100'

完整代码:

with open("input.txt","r") as inp:
     for line in inp:
          name=re.findall("<(\w+)>[\s\S]+?-(\d+)#",line)[0]
          others=re.findall("\|(\d+)#",line)
          print name+" | "+" | ".join(others) if others else " "

答案 3 :(得分:2)

对于您的文件的一行:

test='<amar>[amar-1000#Fem$$$_Y](1){india|1000#Fem$$$,mumbai|1000#Mas$$$}'

替换&lt;使用空字符并删除&gt;之后的所有内容获得名字

echo $test | sed -e 's/<//g' | sed -e 's/>.*//g'

获取所有4位数字符套件:

echo $test |  grep -o '[0-9]\{4\}'

用您喜欢的分隔符替换空格

sed -e 's/ /|/g'

这将使:

echo $(echo $test | sed -e 's/<//g' | sed -e 's/>.*//g') $(echo $test |  grep -o '[0-9]\{4\}') | sed -e 's/ /|/g'

这将输出:

阿玛尔| 1000 | 1000 | 1000

使用快速脚本得到它:your_script.sh input_file output_file

#!/bin/bash

IFS=$'\n' #line delimiter

#empty your output file
cp /dev/null "$2"

for i in $(cat "$1"); do
    newline=`echo $(echo $i | sed -e 's/<//g' | sed -e 's/>.*//g') $(echo $i |  grep -o '[0-9]\{4\}') | sed -e 's/ /|/g'`
    echo $newline >> "$2"
done

cat "$2"