【问题标题】:Shell scripting to find the delimiter用于查找分隔符的 Shell 脚本
【发布时间】:2015-09-01 16:28:52
【问题描述】:

我有一个包含三列的文件,其中有管道作为分隔符。由于某些错误,现在文件中的某些行可以有“,”而不是“|”。我想输出所有这些错误的行。

【问题讨论】:

  • 你走了多远?您希望有人为您解决这个问题,还是只为您提供指导?
  • 我不知道在这种情况下可以使用哪个命令。
  • 我什至没有足够清楚地理解用例或问题陈述。你想计算每个字符吗?还是每个字?如果是字符,垂直分隔符有什么作用?
  • 是的,这是我的要求之一。因此,对于三列,分隔符计数为每行两个。如果任何一行的管道少于两个或多于两个,我想打印这些行。
  • 你完全改变了你的问题陈述,从每行计算字符到一个新的问题陈述,我们只得到每行正好包含三列的信息,有些带有“|”还有一些带有“,”。而现在你只想统计 ",":s 的出现次数?

标签: bash shell awk


【解决方案1】:

你也可以用grep,比较复杂:

egrep "\|.*\|.*\|" input
echo No pipe
egrep "^[^\|]*$" input
echo One pipe
egrep "^[^\|]*\|[^\|\]*$" input
echo 3+ pipe
egrep "\|[^\|]*\|[^\|\]*\|" input

在组合grep之前,先引入新变量 p(管道)和 n(无管道)

p="\|"
n="[^\|]*"
echo "p=$p, n=$n"
echo No pipe
egrep "^$n$" input
echo One pipe
egrep "^$n$p$n$" input
echo 3+ pipe
egrep "$p$n$p$n$p" input

现在把所有东西放在一起

egrep "^$n$|^$n$p$n$|$p$n$p$n$p" input

编辑:cmets 和变量名称是关于“斜杠”的,但它们是管道(带有反斜杠)。这有点令人困惑。

【讨论】:

    【解决方案2】:

    要使用 awk 计算列数,您可以使用 NF 变量:

    $ cat file
    ABC|12345|EAR
    PQRST|123|TWOEYES
    ssdf|fdas,sdfsf
    $ awk -F\| 'NF!=3' file
    ssdf|fdas,sdfsf
    

    但是,这似乎并未涵盖基于问题和 cmets 的各种修订而损坏数据的所有可能方式。

    更好的方法是定义数据必须遵循的准确格式。例如,假设一行是“正确的”,如果它是三列,只有第一个和第三个字母,第二个数字,你可以编写以下脚本来匹配所有不符合要求的行:

    awk -F\| '!(NF==3 && $1$3 ~ /^[a-zA-Z]+$/ && $2+0==$2)' file
    

    测试(注意只有第二行(符合标准的)没有被打印出来):

    $ cat file
    A,BC|12345|EAR
    PQRST|123|TWOEYES
    ssdf|fdas,sdfsf
    ABC|3983|MAKE,
    sf dl lfsdklf |kldsamfklmadkfmask |mfkmadskfmdslafmka
    ABC|abs|EWE
    sdf|123|123
    $ awk -F\| '!(NF==3&&$1$3~/^[a-zA-Z]+$/&&$2+0==$2)' file
    A,BC|12345|EAR
    ssdf|fdas,sdfsf
    ABC|3983|MAKE,
    sf dl lfsdklf |kldsamfklmadkfmask |mfkmadskfmdslafmka
    ABC|abs|EWE
    sdf|123|12
    

    您可以根据您认为有效的输入来调整上述命令以满足您的特定需求。例如,如果您还想将每行的长度限制为 50 个字符,您可以这样做

    awk -F\| '!(NF==3 && $1$3 ~ /^[a-zA-Z]+$/ && $2+0==$2 && length($0)<50)' file
    

    【讨论】:

    • 您的脚本运行良好,但如果输入文件如下所示:
    • ABC|3983|MAKE,这里最后的“,”对我来说也是一个错误。
    • @Programmer 你可以用这个脚本做第二遍:awk -F'[|,]' 'NF!=3' file
    • 这并不能解决我的问题。使用上述方法,我只得到以“,”结尾的行。
    • 例如:如果我有两行 ABC|12345,EAR 和 PQRST|123|TWOEYES,使用你提到的命令,我只得到第二行。
    猜你喜欢
    • 2014-04-23
    • 1970-01-01
    • 1970-01-01
    • 2013-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    相关资源
    最近更新 更多