我需要通过将每行拆分为4段并在每段之间插入一个分隔符(如管道或:)来重建文件。我的问题是结构有些不一致。。。
文件如下所示:
MIKE TESTUSER Some Text 21 - Etc BLA 43 BLA - Some, Additional..12 info
STEVE NOBODY 43 More `Text and So on BLA (MORE ADDITIONAL info)
LEROY ANYONE Again some text chars numbers BLABLA
我需要将其分为名称:地址:城市和可选邮编:可选附加信息
MIKE TESTUSER|Some Text 21 - Etc|BLA43 BLA|- Some, Additional..12 info
STEVE NOBODY|43 More `Text and So on|BLA|(MORE ADDITIONAL info)
LEROY ANYONE|Again some text chars, numbers|BLABLA
第一段总是大写,没有数字或特殊字符第二段包含除大写单词以外的任何内容第三段仅为大写,有时为数字最后一段可以是除大写中的单词以外的任何内容
如果有人能解决这个问题,或者能给我指明一个方向,让我接近(不一定是完美的),那就太好了
首先感谢您的快速回复!我试着用空格将每一行分解成数组元素,然后检查每个元素的大小写、数字等,有点像charlies-awk方法。问题是,我不能总是确定何时必须放置分隔符,因为一个段有时以数字或非字母数字字符结束,而下一个段以数字/非字母数字字母字符开始。
例如
此名称23 Rue da guerre 321 12345 MARSEILLE-信息
应该看起来像
此名称| 23 Rue da guerre 321 | 12345 MARSEILLE |-信息
这个文件有几千行,真的很乱。通常是邮政编码出现在城市的前面,有时出现在城市后面,再加上其他各种不一致之处。。
我知道在任何情况下我都必须手动重新编辑它,但我希望能找到一个解决方案使其不那么耗时:)
它一定只是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
}'
其想法是检查每个以空格分隔的字段的大小写,并保留一个标志以记住您是在运行大写项目还是小写项目。所做的更改是将管道角色添加到输出中。
您确实需要像Perl这样全面的语言。它应该是这样的:
use strict;
use warnings;
open MY_FILE "myFileName" or die qq(Can't open "myFileName" for readingn);
while (my $line = <MY_FILE>) {
chomp $line;
$line =~ /([A-Zs]+)(.*)([A-Zds]{2,})(.*);
print join "|", ($1, $2, $3, $4) . "n";
}
最大的诀窍是中的正则表达式
$line =~ /([A-Zs]+)(.*)([A-Zds])(.*);
这就是将线分成四部分的原因(然后用$1
到$4
表示)。我甚至没有足够的数据来开始测试它
你能为你的问题附上大约4到5行的文件吗?我会解决的?
这可能对您有用:
sed 's/^([A-Z ]*) (.*)/2n1|/;s/[A-Z]{2}/|&/;s/([^|]*|)(.*)/21/;s/([^A-Z0-9 ])/|1/;s/([^n]*)n(.*)/21/;s/|$//' file