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是指