Bash 如何将具有空格和空格的表解析为结构/标记化?
我必须将表解析为数组或标记化,但保留位置,例如:Bash 如何将具有空格和空格的表解析为结构/标记化?,bash,Bash,我必须将表解析为数组或标记化,但保留位置,例如: $cat t.txt ID Name Callin Link Auth CCOS Msg Channel Priv Limit 1 false false true USER 2 Administrator false false true ADMINISTRATOR “USER”的字段值应该是6,而大多数代码给我的是
$cat t.txt
ID Name Callin Link Auth CCOS Msg Channel Priv Limit
1 false false true USER
2 Administrator false false true ADMINISTRATOR
“USER”的字段值应该是6,而大多数代码给我的是5,即使使用字段分隔符作为制表符
我对空白字段有困难。如何有效地将其添加到数组中
我尝试过的代码,它们都跳过空白值而不捕获它:
while read col1 col2 col3 col4 col5 col6
do
echo "Col1 : $col1"
echo "Col2 : $col2"
echo "Col3 : $col3"
echo "Col4 : $col4"
echo "Col5 : $col5"
echo "Col6 : $col6"
done < t.txt
理想情况下,我希望字段打印为
echo field[0], field[6] # 1 , USER and 2, ADMINISTRATOR
$sed-e's/^\([0-9]*\)\s.*\s\([^]*\)$/\1,2/g'
$sed-e's/^\([0-9]*\)\s.*\s\([^]*\)$/\1,2/g'
如果您的文件确实有制表符分隔符,awk将正确解析它。如果它只有空格,GNU awk可以在固定宽度的边界上进行解析。如果两者都没有,你将不得不以某种方式对其进行预处理;你不能分析没有的东西
在获取数据时,我添加了制表符分隔符。我查找任意两个空格字符串,后跟一个非空格,并专门处理第一行数据:
$ sed -E 's/ ([^ ])/\t\1/g; s/^1/1\t/;' fixed.dat | cat -vt
ID^IName ^ICallin^ILink Auth^ICCOS Msg ^IChannel Priv Limit
1^I ^Ifalse ^Ifalse ^Itrue ^IUSER
2 ^IAdministrator ^Ifalse ^Ifalse ^Itrue ^IADMINISTRATOR
只需使用awk查找即可解析的:
$ sed -E 's/ ([^ ])/\t\1/g; s/^1/1\t/;' fixed.dat | awk -F\\t '{print $6}'
Channel Priv Limit
USER
ADMINISTRATOR
要在GNU awk中使用固定宽度列,请设置FIELDWIDTHS字符串。在这里,它是以编程方式完成的:
BEGIN {
titles = "ID Name Callin Link Auth CCOS-Msg Channel-Priv-Limit"
pos = 1
sep = ""
while( match(substr(titles, pos), / +/) > 0 ) {
pos += RSTART + RLENGTH - 1
FIELDWIDTHS = FIELDWIDTHS sep RSTART + RLENGTH - 1
sep = " "
}
FIELDWIDTHS = FIELDWIDTHS sep length(titles) - pos
print "FIELDWIDTHS:", FIELDWIDTHS
}
{
OFS = "|"
print $1, $2, $3, $4, $5, $6, $7, $8, $9
}
结果:
$ awk -f fixed.awk fixed.dat
FIELDWIDTHS: 4 13 8 5 6 11 17
ID |Name |Callin |Link |Auth |CCOS Msg |Channel Priv Limi||
1 | | fals|e f|alse | true | USER||
2 |Administrator| fals|e f|alse | true | ADMINISTRATOR||
这有点错误,因为它使用标题行来计算列偏移量,而标题没有在数据上对齐。但是,如果这是您的情况,您可以查看如何修复FIELDWIDTHS字符串以解析列
如果您不确定给定的行有什么问题,我最喜欢的检查行的方法有点复杂,但非常快速且不可破坏:
$ sed -E 's/ ([^ ])/\t\1/g; s/^1/1\t/;' fixed.dat |
sed -ne '2 {p;q;}' | tr \\t \\n | nl -ba
1 1
2
3 false
4 false
5 true
6 USER
sed(1)选择要打印的行(如果文件太大,退出速度会更快)tr(1)将分隔符转换为换行符,nl(1)对行进行编号,以便知道哪个字段是哪个字段。如果该行缺少选项卡,则会快速显示:
$ sed -E 's/ ([^ ])/\t\1/g' fixed.dat | sed -ne '2 {p;q;}' | tr \\t \\n | nl -ba
1 1
2 false
3 false
4 true
5 USER
如果可以的话,我的最后一条建议是:不要使用shell解析文件。除了专门为解析而设计之外,awk速度更快,因为1)循环不被解释,2)脚本作为单个进程执行。如果您在shell中循环任何不是文件名列表的内容,那么您的工作太辛苦了 如果文件确实有制表符分隔符,awk将正确解析它。如果它只有空格,GNU awk可以在固定宽度的边界上进行解析。如果两者都没有,你将不得不以某种方式对其进行预处理;你不能分析没有的东西 在获取数据时,我添加了制表符分隔符。我查找任意两个空格字符串,后跟一个非空格,并专门处理第一行数据:
$ sed -E 's/ ([^ ])/\t\1/g; s/^1/1\t/;' fixed.dat | cat -vt
ID^IName ^ICallin^ILink Auth^ICCOS Msg ^IChannel Priv Limit
1^I ^Ifalse ^Ifalse ^Itrue ^IUSER
2 ^IAdministrator ^Ifalse ^Ifalse ^Itrue ^IADMINISTRATOR
只需使用awk查找即可解析的:
$ sed -E 's/ ([^ ])/\t\1/g; s/^1/1\t/;' fixed.dat | awk -F\\t '{print $6}'
Channel Priv Limit
USER
ADMINISTRATOR
要在GNU awk中使用固定宽度列,请设置FIELDWIDTHS字符串。在这里,它是以编程方式完成的:
BEGIN {
titles = "ID Name Callin Link Auth CCOS-Msg Channel-Priv-Limit"
pos = 1
sep = ""
while( match(substr(titles, pos), / +/) > 0 ) {
pos += RSTART + RLENGTH - 1
FIELDWIDTHS = FIELDWIDTHS sep RSTART + RLENGTH - 1
sep = " "
}
FIELDWIDTHS = FIELDWIDTHS sep length(titles) - pos
print "FIELDWIDTHS:", FIELDWIDTHS
}
{
OFS = "|"
print $1, $2, $3, $4, $5, $6, $7, $8, $9
}
结果:
$ awk -f fixed.awk fixed.dat
FIELDWIDTHS: 4 13 8 5 6 11 17
ID |Name |Callin |Link |Auth |CCOS Msg |Channel Priv Limi||
1 | | fals|e f|alse | true | USER||
2 |Administrator| fals|e f|alse | true | ADMINISTRATOR||
这有点错误,因为它使用标题行来计算列偏移量,而标题没有在数据上对齐。但是,如果这是您的情况,您可以查看如何修复FIELDWIDTHS字符串以解析列
如果您不确定给定的行有什么问题,我最喜欢的检查行的方法有点复杂,但非常快速且不可破坏:
$ sed -E 's/ ([^ ])/\t\1/g; s/^1/1\t/;' fixed.dat |
sed -ne '2 {p;q;}' | tr \\t \\n | nl -ba
1 1
2
3 false
4 false
5 true
6 USER
sed(1)选择要打印的行(如果文件太大,退出速度会更快)tr(1)将分隔符转换为换行符,nl(1)对行进行编号,以便知道哪个字段是哪个字段。如果该行缺少选项卡,则会快速显示:
$ sed -E 's/ ([^ ])/\t\1/g' fixed.dat | sed -ne '2 {p;q;}' | tr \\t \\n | nl -ba
1 1
2 false
3 false
4 true
5 USER
如果可以的话,我的最后一条建议是:不要使用shell解析文件。除了专门为解析而设计之外,awk速度更快,因为1)循环不被解释,2)脚本作为单个进程执行。如果您在shell中循环任何不是文件名列表的内容,那么您的工作太辛苦了 是否跳过标题?
sed-e'1{h;d}'-e..
h;d是否要跳过标题?sed-e'1{h;d}'-e..
h;d是指