在 ksh 脚本中使用正则表达式
Using regular expressions in a ksh Script
我有一个文件 (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
然而,无论我在程序终止的行中输入什么,这都无法正确评估。
您的正则表达式看起来 bad - using sites like 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}"
当你想要不匹配的行号时,你可以使用grep -vn
。小心写出正确的正则表达式,你会得到
grep -Evn "^.{9}[+].{3}[+].[+].{2}$" file.txt
这不是您想要的布局,因此请将布局更改为 sed
:
grep -Evn "^.{9}[+].{3}[+].[+].{2}$" file.txt |
sed -r 's/([^:]*):(.*)/Invalid number () check line number ./'
编辑:
我把.{1}
改成了.
.
sed
也超过了顶部。需要spme解释的时候可以从echo "Linenr:Invalid line"
开始
我将正则表达式直接放入条件中得到了有趣的结果:
$ 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-like 语法。如果那里有 optional space,您可以使用 ?(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 手册页的 "File Name Generation" 部分。
我有一个文件 (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
然而,无论我在程序终止的行中输入什么,这都无法正确评估。
您的正则表达式看起来 bad - using sites like 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}"
当你想要不匹配的行号时,你可以使用grep -vn
。小心写出正确的正则表达式,你会得到
grep -Evn "^.{9}[+].{3}[+].[+].{2}$" file.txt
这不是您想要的布局,因此请将布局更改为 sed
:
grep -Evn "^.{9}[+].{3}[+].[+].{2}$" file.txt |
sed -r 's/([^:]*):(.*)/Invalid number () check line number ./'
编辑:
我把.{1}
改成了.
.
sed
也超过了顶部。需要spme解释的时候可以从echo "Linenr:Invalid line"
我将正则表达式直接放入条件中得到了有趣的结果:
$ 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-like 语法。如果那里有 optional space,您可以使用 ?(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 手册页的 "File Name Generation" 部分。