【问题标题】:Using regular expressions in a ksh Script在 ksh 脚本中使用正则表达式
【发布时间】:2018-03-05 18:12:19
【问题描述】:

我有一个文件 (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

但是,无论我在程序终止的行中添加什么,这都不会正确评估。

【问题讨论】:

  • 这不是“Unix 脚本”,这不是一个东西,它是一个 ksh 脚本。
  • 好的,谢谢,更新了。

标签: regex unix ksh


【解决方案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} 显然是多余的;也许在有人笑之前把它拿出来。
  • 教用户阅读grep -n 的输出最终可能是比试图使其正确可读的更好策略。
【解决方案2】:

将正则表达式直接置于条件中,我得到了有趣的结果:

$ 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 模式有一些类似正则表达式的语法。如果其中有一个 可选 空格,您可以使用 ?(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

阅读 ksh 手册页的“文件名生成”部分。

【讨论】:

  • 谢谢!我能够使用最后一个。在第二个“+”之后,可以有一个空格作为字符,你知道有什么方法可以解决这个问题吗?
  • 没关系,问题实际上是默认的 IFS 是空格、制表符或换行符。当我更改 IFS=$'\n' 时,它现在完全符合我的要求。再次感谢!!
【解决方案3】:

您的正则表达式看起来像 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}"

【讨论】:

    猜你喜欢
    • 2010-12-10
    • 1970-01-01
    • 2015-01-08
    • 2010-09-23
    • 2019-07-13
    • 2016-06-25
    • 2019-11-16
    • 1970-01-01
    相关资源
    最近更新 更多