删除仅包含数字的列

删除仅包含数字的列

我有一个包含一些数据的表,我需要删除仅包含数字的列(Nr.,Cod,Tiraj):

Nr.     Autor         Titlu        Cod     Tiraj     Tara
1    Gauss Carl   Aritmetica 1   297485   11454   Germania
2    Gauss Carl   Aritmatica 2   297484   10254   Germania
3    Gauss Carl   Aritmetica 3   297455   45872   Germania

结果应该是这样的:

Autor         Titlu         Tara
Gauss Carl   Aritmetica 1   Germania
Gauss Carl   Aritmatica 2   Germania
Gauss Carl   Aritmetica 3   Germania

列之间由TAB

我用这个创建了表:

.TS
tab(@);
c c c c c c .
Nr.@Autor@Titlu@Cod@Tiraj@Tara
1@Gauss Carl@Aritmetica 1@297485@11454@Germania
2@Gauss Carl@Aritmatica 2@297484@10254@Germania
3@Gauss Carl@Aritmetica 3@297455@45872@Germania
.TE

答案1

您想要从或多或少带有一些垃圾行并用作字段分隔符的CSV 数据集中删除NR.,Cod和列。Tiraj@

sed -e 1,3d -e '$d' file |
csvcut -d @ -C 'Nr.,Cod,Tiraj' |
csvformat -D @

其输出将是

Autor@Titlu@Tara
Gauss Carl@Aritmetica 1@Germania
Gauss Carl@Aritmatica 2@Germania
Gauss Carl@Aritmetica 3@Germania

添加回sed删除的内容并根据新的列数进行调整,然后将其写入新文件:

{
    printf '%s\n' .TS 'tab(@);' 'l l l .'
    sed -e 1,3d -e '$d' file |
    csvcut -d @ -C 'Nr.,Cod,Tiraj' |
    csvformat -D @
    echo .TE
} >file.new

csvcut和实用程序csvformat是 csvkit 的一部分,csvkit 是一个用于处理 CSV 文件的工具包,可从https://csvkit.readthedocs.io/en/latest/

最终表格将使用 进行排版nroff -t file.new

您还可以通过运行初始管道的输出来获得表的变体column -s @ -t

$ sed -e 1,3d -e '$d' file | csvcut -d @ -C 'Nr.,Cod,Tiraj' | csvformat -D @ | column -s @ -t
Autor       Titlu         Tara
Gauss Carl  Aritmetica 1  Germania
Gauss Carl  Aritmatica 2  Germania
Gauss Carl  Aritmetica 3  Germania

或者,您可以使用csvlook

$ sed -e 1,3d -e '$d' file | csvcut -d @ -C 'Nr.,Cod,Tiraj' | csvlook
| Autor      | Titlu        | Tara     |
| ---------- | ------------ | -------- |
| Gauss Carl | Aritmetica 1 | Germania |
| Gauss Carl | Aritmatica 2 | Germania |
| Gauss Carl | Aritmetica 3 | Germania |

...取决于你是什么实际上想要作为输出。

答案2

尝试这个笨拙的概念证明。它基于列始终是数字或非数字的假设。

awk -F"\t" '
NR==1   {split($0, HDRSV)                                       # save header fields for later use
         next
        }
NR==2   {for (i=1; i<=NF; i++)  if ($i+0 != $i) PR[++IX] = i    # check if column is non-numeric and
                                                                # save col nr for print
         for (i=1; i<=IX; i++) printf "%s\t", HDRSV[PR[i]]      # print header fields
         printf ORS                                             # and line terminator
        }
        {for (i=1; i<=IX; i++) printf "%s\t", $PR[i]            # print each line´s fields
         printf ORS                                             # and line terminator
        }
' file
Autor   Titlu   Tara    
Gauss Carl  Aritmetica1 Germania    
Gauss Carl  Aritmatica2 Germania    
Gauss Carl  Aritmetica3 Germania    

答案3

使用(以前称为 Perl_6)

~$ cat authors.tr | raku -ne '.split( / [^ | \S] [\d+]+ %% "\@" /, :skip-empty).join("\@").put;' | raku -ne '++$ == 4 ?? .split("\@")[1,2,5].join("\@").put !! .put;' | nroff -t -Tascii

输入示例:

TS
tab(@);
c c c c c c .
Nr.@Autor@Titlu@Cod@Tiraj@Tara
1@Gauss Carl@Aritmetica 1@297485@11454@Germania
2@Gauss Carl@Aritmatica 2@297484@10254@Germania
3@Gauss Carl@Aritmetica 3@297455@45872@Germania
.TE

示例输出:

  Autor         Titlu         Tara
Gauss Carl   Aritmetica 1   Germania
Gauss Carl   Aritmatica 2   Germania
Gauss Carl   Aritmetica 3   Germania

作为一项挑战,我决定尝试编写一个 Raku 单行代码(好吧,两行代码:一行用于标题,一行用于数据列),以修改authors.trnroff/groff 源文件。一个棘手的方面是,很难确定整个字段是否仅由数字组成:内部(非最左/非最右)列肯定会被列分隔符包围,但终端(最左/最右)则不会。

我最终发现了这样一个事实:(至少对于给定的列)第一个正则表达式原子应该是[^ | \S].正则表达式的其余部分由 Raku 漂亮的“修改量词”处理%%,它识别重复(按列)模式,例如[\d+]+ %% "\t",这意味着'一列或多列--\d+由制表符分隔,允许尾随制表符'。上面的正则表达式删除所有以数字结尾的列,但前面包含空格的列除外(如列Aritmetica 1)。

但实际上,这工作量太大了。更简单:

  1. 删除.line_#3 末尾的句点,并在 nroff/groff 列格式部分插入新的 l​​ine_#4,该部分指定N数字列与A字母列(非标题、数据),
  2. 使用 Raku 解析标头(下面的示例使用N A A N N A . as new line_#4),并且
  3. 删除那些指定的列N
~$ cat authors2.tr  |  raku -e 'my @a=lines; \
    @a[2..3] = @a[2..3]>>.comb>>.[0,2,4...*];    \
    @a[4..7].=map: *.split("\@", :skip-empty);   \
    my $n    = @a[3].grep({!/ N /}, :k ).list;   \
    @a[2]    = @a[2][ |$n.head(*-1)];  @a[3] = @a[3][ |$n];  \
    @a[4..7].=map: *.[ |$n.head(*-1)].join("\@");  .put for @a;' 

示例输出(有效 nroff/groff):

.TS
tab(@);
c c c
A A A .
Autor@Titlu@Tara
Gauss Carl@Aritmetica 1@Germania
Gauss Carl@Aritmatica 2@Germania
Gauss Carl@Aritmetica 3@Germania
.TE

示例输出(之后nroff -t -Tascii):

  Autor         Titlu         Tara
Gauss Carl   Aritmetica 1   Germania
Gauss Carl   Aritmatica 2   Germania
Gauss Carl   Aritmetica 3   Germania

https://raku.org

答案4

$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==FNR {
    if ( NR > 1 ) {
        for ( i=1; i<=NF; i++ ) {
            if ( $i != ($i+0) ) {
                isGood[i]
            }
        }
    }
    next
}
{
    out = sep = ""
    for ( i=1; i<=NF; i++ ) {
        if ( i in isGood ) {
            out = out sep $i
            sep = OFS
        }
    }
    print out
}

$ awk -f tst.awk file file
Autor   Titlu   Tara
Gauss Carl      Aritmetica 1    Germania
Gauss Carl      Aritmatica 2    Germania
Gauss Carl      Aritmetica 3    Germania

相关内容