首页 > 解决方案 > awk 解决方案,用于按列搜索任何字符的第一个实例(但一个!)

问题描述

我有一个(先前排序的)文本文件,由破折号-或单个字母字符组成。我非常感谢任何有助于更好地理解正确的 awk 语法以遍历文本文件的每一列,如果存在非破折号字符,则仅保留每行中的第一个非破折号字符,否则保留该破折号字符如果不存在字母字符。任何一种情况下的结果都是单行文本。文件总是以这样一种方式格式化,即每行都有相同的列数,并且总是首选第一个非破折号字符,不管“较低”行中是否存在其他字母字符。

两个例子来澄清:给定这个文本文件:

# printf 't---k-\ncha---\n--nn--\n--ab-s\n'

t---k-
cha---
--nn--
--ab-s

该程序将从第一列开始,并且因为第一个字符不是破折号,它会保留一个t. 然后我们将继续到下一列,其中第一行信息是一个破折号,因此前进到第二行,其中h选择了 an。然后您将前进到第三列,并且必须移动到第三行以选择n字符等。要报告的预期字符串是:

thanks.

在第二个示例中,我们有一个非常相似的文本排列,但有一个例外:

#printf 't-----\ncha---\n--nn--\n--ab-s\n'

t-----
cha---
--nn--
--ab-s

请注意,在第二个示例中,第四列中没有字母字符。因为不存在这样的字符,我们将在该位置返回一个破折号。因此,预期的输出将是:

than-s

这篇文章重点介绍了一种类似于我想要实现的 pandas 方法,这篇文章同样通过 numpy 提供了一个解决方案,但我相信它们都需要适用于整数的函数,而我有一个由字母字符组成的数据集。这篇文章类似地解释了一种使用 awk 以列方式应用函数的方法,这更接近我所追求的,就像其他awk 文章一样。在我看来,我所追求的 awk 方法同样需要我声明一个按列的方法,我认为它在函数的开头说明为:

awk '{for (i=1;i<=NF;i++){

...我被困的地方是试图识别函数的下一个参数,我认为我在使用某种类型的 if/else 语句。这是我希望得到进一步澄清的部分。

也许解决方案不需要通过awk 完成——我当然愿意接受其他依赖于任何语言的策略,所以如果 Python 或 Perl 或其他一些策略显然是更合适的语言,谢谢你的教育。

感谢您的考虑

标签: awk

解决方案


在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ cat tst.awk
{
    numChars = length($0)
    for (i=1; i<=numChars; i++) {
        if ( chars[i] ~ /^-?$/ ) {
            chars[i] = substr($0,i,1)
        }
    }
}
END {
    for (i=1; i<=numChars; i++) {
        printf "%s%s", chars[i], (i<numChars ? "" : ORS)
    }
}

$ awk -f tst.awk file1
thanks

$ awk -f tst.awk file2
than-s

推荐阅读