Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于使用复杂模式重建部分不一致文件的bash/regex_Regex_Bash_Sed_Awk - Fatal编程技术网

用于使用复杂模式重建部分不一致文件的bash/regex

用于使用复杂模式重建部分不一致文件的bash/regex,regex,bash,sed,awk,Regex,Bash,Sed,Awk,我需要重建一个文件,将每一行分割成4段,并在每段之间插入一个像管道或:的分隔符。我的问题是结构有些不一致 该文件如下所示: MIKE TESTUSER一些文本21-Etc BLA 43 BLA-Some,其他..12信息 STEVE NOBODY 43更多`文本等BLA(更多附加信息) 勒罗伊:有人再发一些短信吗 我需要把它分为姓名:地址:城市和可选的邮政编码:可选的附加信息 MIKE TESTUSER |一些文本21-等等| BLA43 BLA |-一些,附加..12信息 STEVE NOB

我需要重建一个文件,将每一行分割成4段,并在每段之间插入一个像管道或:的分隔符。我的问题是结构有些不一致

该文件如下所示:

MIKE TESTUSER一些文本21-Etc BLA 43 BLA-Some,其他..12信息
STEVE NOBODY 43更多`文本等BLA(更多附加信息)
勒罗伊:有人再发一些短信吗
我需要把它分为姓名:地址:城市和可选的邮政编码:可选的附加信息

MIKE TESTUSER |一些文本21-等等| BLA43 BLA |-一些,附加..12信息
STEVE NOBODY | 43更多`文本等| BLA |(更多附加信息)
LEROY any |又是一些文本字符、数字|等等
第一段总是大写,没有数字或特殊字符 第二段由除大写单词以外的任何内容组成 第三段仅为大写字母,有时为数字 最后一段可以是除大写单词以外的任何内容

如果有人能解决这个问题,或者能为我指出一个让我接近的方向,那就太好了(不一定是完美的)


首先感谢您的快速回复!我尝试使用空格将每一行分解成数组元素,然后检查每个元素的大小写、数字等,有点像charlies-awk方法。问题是,我不能总是确定何时必须放置分隔符,因为一段有时以数字或非字母数字字符结尾,而下一段则以数字/非字母数字字符开头

比如说

姓名:23 Rue da guerre 321 12345马赛-信息

应该像

此名称|达格雷街23号321 | 12345马赛|-信息

这个文件有几千行,非常凌乱。通常是邮政编码 出现在城市的前面,有时在城市的后面,还有其他各种不一致之处

我知道在任何情况下都必须手动重新编辑,但我希望找到一个解决方案
使它不那么耗时:)

它必须是bash吗?我会认真考虑写一些简单的Awk程序

比如说,作为一个开始

awk -f 'BEGIN {FS=" "; uplow=0;}
              {uplow=1;
               for(i=1; i < $NF; i++){
                  if(uplow && ($i ~ [A-Z])) out += $i+" "
                  else if (uplow && ($i !~ [A-Z])) {
                       uplow = 0;
                       out += "|"
                  } else if # fill in the other cases
                }
                print out
               }'
awk-f'BEGIN{FS=”“;uplow=0;}
{uplow=1;
对于(i=1;i<$NF;i++){
如果(上传和($i~[A-Z])输出+=$i+“”
else if(uplow&($i!~[A-Z])){
uplow=0;
out+=“|”
}否则,请填写其他案例
}
打印出来
}'

其思想是检查每个空格分隔字段的大小写,并保留一个标记以记住您是在运行大写项目还是小写项目。更改的内容是将管道字符添加到输出中。

您确实需要像Perl这样成熟的语言。应该是这样的:

使用严格;
使用警告;
打开我的文件“myFileName”或死亡qq(无法打开“myFileName”进行读取\n);
while(我的$line=){
chomp$行;
$line=~/([A-Z\s]+)(.*)([A-Z\d\s]{2,})(.*);
打印联接“|”,($1,$2,$3,$4)。“\n”;
}
最大的诀窍是正则表达式:

$line =~ /([A-Z\s]+)(.*)([A-Z\d\s])(.*);
这就是将行分成四个部分的原因(然后由
$1
$4
表示)。我没有足够的数据来测试它


你能在你的问题上附上大约4到5行的文件吗?我会解决一些问题的。

这可能适合你:

sed 's/^\([A-Z ]*\) \(.*\)/\2\n\1|/;s/[A-Z]\{2\}/|&/;s/\([^|]*|\)\(.*\)/\2\1/;s/\([^A-Z0-9 ]\)/|\1/;s/\([^\n]*\)\n\(.*\)/\2\1/;s/|$//' file

到目前为止你试过什么?我们不应该从头开始为您编写此代码:-)您的规则有歧义:在上一个示例中,第二个分隔符可能位于
321
之前或
12345
之后。