Bash Shell脚本以查找分隔符

Bash Shell脚本以查找分隔符,bash,shell,awk,Bash,Shell,Awk,我有一个包含三列的文件,其中以管道作为分隔符。现在,由于某些错误,文件中的某些行可以使用a而不是|。我想输出所有这些错误行。要使用awk计算列数,可以使用NF变量: $ cat file ABC|12345|EAR PQRST|123|TWOEYES ssdf|fdas,sdfsf $ awk -F\| 'NF!=3' file ssdf|fdas,sdfsf 然而,这似乎并没有涵盖根据对问题和评论的各种修订,数据可能被破坏的所有可能方式 更好的方法是定义数据必须遵循的确切格式。例如,假设一行

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

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

$ cat file
ABC|12345|EAR
PQRST|123|TWOEYES
ssdf|fdas,sdfsf
$ awk -F\| 'NF!=3' file
ssdf|fdas,sdfsf
然而,这似乎并没有涵盖根据对问题和评论的各种修订,数据可能被破坏的所有可能方式

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

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

您也可以使用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

编辑:注释和变量名是关于斜杠的,但它们是带有反斜杠的管道。这有点让人困惑。

你已经走了多远?你想要有人帮你解决这个问题,还是只给你指路?我不知道在这种情况下可以使用哪个命令。我甚至都不太清楚用例或问题陈述。你想数一数每个字符吗?还是每一个字?如果是字符,垂直分隔符有什么用途?是的,这是我的要求之一。因此,对于三列,分隔符计数为每行两个。如果任何一行少于两个或多于两个管道,我想打印这些行。您完全改变了您的问题陈述,从每行计算字符数改为新的问题陈述,其中我们只得到每行正好包含三列的信息,有些带有|,有些带有,。现在,您只想计算,:s的次数?您的脚本运行良好,但如果输入文件如下所示:ABC | 3983 | MAKE,这里,结尾的也是一个错误。@Programmer您可以使用此脚本进行第二次传递:awk-F'[|,]''NF=这不能解决我的问题。使用上述方法,我只得到以结尾的行。例如:如果我有两行ABC | 12345、EAR和PQRST | 123 | TWOEYES,使用您提到的命令,我只得到第二行。