在ksh脚本中使用正则表达式

时间:2018-03-05 18:12:20

标签: regex unix ksh

我有一个文件(file.txt),其中包含一些文字,如:

  • 000000000 + 000 + 0 + 00
  • 000000001 + 000 + 0 + 00
  • 000000002 + 000 + 0 + 00

我正在尝试检查每一行以确保它遵循以下格式: 字符* 9," +",字符* 3," +"等

到目前为止,我有:

#!/bin/ksh
file=file.txt
line_number=1
for line in $(cat $file)
do
    if [[ "$line" != "[[.]]{9}+[[.]]{3}+[[.]]{1}+[[.]]{2} ]" ]]
    then
        echo "Invalid number ($line) check line $line_number"
        exit 1
    fi
    let "line_number++"
done

然而,无论我在程序终止的行中放置什么,这都无法正确评估。

3 个答案:

答案 0 :(得分:1)

如果需要不匹配的行号,可以使用grep -vn。小心写正确的正则表达式,你将有

grep -Evn "^.{9}[+].{3}[+].[+].{2}$" file.txt 

这不在您想要的布局中,因此请使用sed更改布局:

grep -Evn "^.{9}[+].{3}[+].[+].{2}$" file.txt |
   sed -r 's/([^:]*):(.*)/Invalid number (\2) check line number \1./'

编辑:
我将.{1}更改为. sed也位居榜首。当您需要spme解释时,可以从echo "Linenr:Invalid line"

开始

答案 1 :(得分:0)

您的正则表达式查看bad - 使用https://regex101.com/等网站非常非常有帮助。根据您的描述,我怀疑它看起来应该更像是其中之一;

  • ^.{9}\+.{3}\+.{1}\+.{2}$
  • ^[^\+]{9}\+[^\+]{3}\+[^\+]{1}\+[^\+]{2}$
  • ^[0-9]{9}\+[0-9]{3}\+[0-9]{1}\+[0-9]{2}$

来自[[上的ksh manpage部分 - 您可能希望使用=~

string =~ ere
    True if string matches the pattern ~(E)ere where ere is an extended regular expression.

注意:据我所知,ksh正则表达式不遵循正常语法

使用grep

可能会更好运
# X="000000000+000+0+00"
# grep -qE "^[^\+]{9}\+[^\+]{3}\+[^\+]{1}\+[^\+]{2}$" <<<"${X}" && echo true
true

或者:

if grep -qE "^[^\+]{9}\+[^\+]{3}\+[^\+]{1}\+[^\+]{2}$" <<<"${line}"
then
    exit 1
fi

您可能还希望使用类似下面的结构来处理文件:

while read line; do
    echo "${line}";
done < "${file}"

答案 2 :(得分:0)

我有正确的结果将正则表达式直接置于条件中:

$ line='000000000+000+0+00'
$ [[ $line =~ ^.{9}\+.{3}\+.\+..$ ]] && echo ok
ksh: syntax error: `~(E)^.{9}\+.{3}\+.\+..$ ]] && echo ok
' unexpected

但是如果我将正则表达式保存在变量中:

$ re="^.{9}\+.{3}\+.\+..$"
$ [[ $line =~ $re ]] && echo ok
ok

所以你可以做到

#!/bin/ksh
file=file.txt
line_number=1
re="^.{9}\+.{3}\+.\+..$"
while IFS= read -r line; do
    if [[ ! $line =~ $re ]]; then
        echo "Invalid number ($line) check line $line_number"
        exit 1
    fi
    let "line_number++"
done < "$file"

您也可以使用普通的glob模式:

if [[ $line != ?????????+???+?+?? ]]; then echo error; fi

ksh glob模式有一些类似regex的语法。如果那里有可选空间,您可以使用?(sub-pattern)语法处理

pattern="?????????+???+?( )?+??"

line1="000000000+000+0+00"
line2="000000000+000+ 0+00"

[[ $line1 == $pattern ]] && echo match || echo no match  # => match
[[ $line2 == $pattern ]] && echo match || echo no match  # => match

阅读&#34;文件名生成&#34; ksh手册页的一部分。