将几千行txt解析为行和列

将几千行txt解析为行和列

手头的文件列出了数千名用户的名称、凭据、角色和权限。它以 .xls 的形式传递给我,但行和列没有以正确的形式排列。我已经使用 awk 和 sed 重新格式化了原始文件,现在我有许多具有一致格式的行,如下所示:

ID       ;email                     ;role  ;privilege ;access-to
8charID1 ;[email protected] ;usr   ;read      ;finance ;HR ;accounting; dev
8charID2 ;[email protected] ;mgr   ;rwx       ;finance
8charID3 ;[email protected] ;usr   ;rx        ;marketing ;dev ;doc
.
.
n x 1,000 number of users

但我被困在下一步了。

目标:重新打印行,以便在存在多个访问字段(如第 1 行或第 3 行)的情况下,根据访问字段的数量重新打印所有前面的字段,并将访问字段重新排序为单个列。

ID       ;email                     ;role  ;privilege ;access-to
abcuser1 ;[email protected] ;usr   ;read      ;finance
abcuser1 ;[email protected] ;usr   ;read      ;HR
abcuser1 ;[email protected] ;usr   ;read      ;accounting
abcuser1 ;[email protected] ;usr   ;read      ;dev
user2def ;[email protected] ;mgr   ;rwx       ;finance
zyxuser3 ;[email protected] ;usr   ;rx        ;marketing
zyxuser3 ;[email protected] ;usr   ;rx        ;dev
zyxuser3 ;[email protected] ;usr   ;rx        ;publication
.
.
.
n x 1,000 number of users

答案1

awk -F';' -v OFS=';' '
    { for (i=5; i<=NF; i++) print $1,$2,$3,$4,$i }
' file

输出

ID       ;email                     ;role  ;privilege ;access-to
8charID1 ;[email protected] ;usr   ;read      ;finance 
8charID1 ;[email protected] ;usr   ;read      ;HR 
8charID1 ;[email protected] ;usr   ;read      ;accounting
8charID1 ;[email protected] ;usr   ;read      ; dev
8charID2 ;[email protected] ;mgr   ;rwx       ;finance
8charID3 ;[email protected] ;usr   ;rx        ;marketing 
8charID3 ;[email protected] ;usr   ;rx        ;dev 
8charID3 ;[email protected] ;usr   ;rx        ;doc

答案2

以下是与 Glenn 的解决方案相同的基本思想,但使用 Perl 语言:

$ perl -F";" -lane '$"=";";print "@F[0..3];", $_ for @F[4..$#F]' file 
ID       ;email                     ;role  ;privilege ;access-to
8charID1 ;[email protected] ;usr   ;read      ;finance 
8charID1 ;[email protected] ;usr   ;read      ;HR 
8charID1 ;[email protected] ;usr   ;read      ;accounting
8charID1 ;[email protected] ;usr   ;read      ; dev
8charID2 ;[email protected] ;mgr   ;rwx       ;finance
8charID3 ;[email protected] ;usr   ;rx        ;marketing 
8charID3 ;[email protected] ;usr   ;rx        ;dev 
8charID3 ;[email protected] ;usr   ;rx        ;doc

解释

  • -a:使 perl 的行为类似于awk,自动将每一行分割成空格上的字段(默认情况下,请参阅-F)并将它们保存在@F数组中。
  • -e:让您在命令行上给出脚本。
  • -n:逐行读取输入文件。
  • -lprint:删除尾随换行符并为每个调用添加换行符。
  • -F: 就像awk,输入字段分隔符。在这里,我们将其设置为;

诚然,该脚本有点神秘,但算法非常简单:打印前四个字段,并对每个字段重复 >4。

  • $"=";":特殊变量$"是列表分隔符。这是在打印数组时在数组的每个元素之间打印的。在这里,我将其设置为;,这样我们就可以根据需要打印字段列表。

  • @F[0..3]:这是一个数组切片。它是数组的前 4 个元素@F;当前行的 - 分隔字段)

  • @F[4..$#F]:另一个数组切片。这个是从第 5 个元素@F到最后一个元素($#array是 Perl 中数组的最大索引)。

整个 print 命令只是惯用的 Perl 命令:

## For each element of the array slice
foreach $field (@F[4..$#F]){
  ## print the first 4 fields and a ';', The fields 
  ## are printed separated by ";" because of the $" above.
  print "@F[0..3];";
  ## In the golfed version, the $_ is equivalent to $field here
  print "$field\n"
}

相关内容