我的日志文件(在txt中)包含以下文字
UNIT PHYS STATE LOCATION INFO
TCSM-1098 SE-NH -
ETPE-5-0 1403 SE-OU BCSU-1 ACTV FLTY
ETIP-6 1402 SE-NH -
他们被空间界定了...... 我如何获得如下的输出?
UNIT|PHYS|STATE|LOCATION|INFO
TCSM-1098||SE-NH||-
ETPE-5-0|1403|SE-OU|BCSU-1|ACTV FLTY
ETIP-6|1402|SE-NH||-
提前感谢
这是我到目前为止所尝试的
cat file.txt | awk 'BEGIN { FS = "[[:space:]][[:space:]]+" } {print $1,$2,$3,$4}' | sed 's/ /|/g'
它产生这样的输出
|UNIT|PHYS|STATE|LOCATION|INFO|
|TCSM-1098|SE-NH|-|
|ETPE-5-0|1403|SE-OU|BCSU-1|ACTV|FLTY
|ETIP-6|1402|SE-NH|-|
该栏目并不像我希望的那样
答案 0 :(得分:4)
它似乎没有分隔,而是固定宽度格式。
$ perl -ple '
$_ = join "|",
map {s/^\s+|\s+$//g;$_}
unpack ("a11 a5 a6 a22 a30",$_);
' <file.txt
如何运作
-e:内联命令
解包函数:获取定义的格式和输入行并返回数组
答案 1 :(得分:2)
Perl救援!
perl -wE 'my @lengths;
$_ = <>;
push @lengths, length $1 while /(\S+\s*)/g;
$lengths[-1] = "*";
my $f;
say join "|",
map s/^\s+|\s+$//gr,
unpack "A" . join("A", @lengths), $_
while (!$f++ or $_ = <>);' -- infile
格式不是空白分隔,而是固定宽度。
@lengths数组将填充从输入的第一行获取的列的宽度。最后一列宽度已替换为*
,因为其宽度无法从标题中推断出来。
然后,根据用于解析文件的长度创建unpack模板。
$f
只是一个标志,可以将模板应用于标题行本身。
答案 2 :(得分:1)
用FIELDWITDHS的GNU awk来处理固定宽度的字段:
awk -v FIELDWIDTHS='11 5 6 22 99' -v OFS='|' '{$1=$1; gsub(/ *\| */,"|"); sub(/ +$/,"")}1' file
UNIT|PHYS|STATE|LOCATION|INFO
TCSM-1098||SE-NH||-
ETPE-5-0|1403|SE-OU|BCSU-1|ACTV FLTY
ETIP-6|1402|SE-NH||-
我认为这是非常明确和不言自明的,但如果您有任何问题,请告诉我。
答案 3 :(得分:0)
手动,在awk
:
$ awk 'BEGIN{split("11 5 6 23 99", cols); }
{s=0;
for (i in cols) {
field = substr($0, s, cols[i]);
s += cols[i];
sub(/^ */, "", field);
sub(/ *$/, "", field);
printf "%s|", field;
};
printf "\n" } ' file
UNIT|PHYS|STATE|LOCATION|INFO|
TCSM-1098||SE-NH||-|
ETPE-5-0|1403|SE-OU|BCSU-1|ACTV FLTY|
ETIP-6|1402|SE-NH||-|
列的宽度在BEGIN
块中设置,然后对于每一行,我们获取所需长度的行的子串。 s
计算当前列的起始位置,sub()
调用删除前导和尾随空格。这样的代码在每一行上打印一个尾随|
,但这可以通过使第一列或最后一列成为特殊情况来解决。
请注意,最后一个字段与输出中的字段不同,很难说明ACTV
和FLTY
之间的分割位置。是固定宽度,还是空间是分隔符?