我有一个我正在验证的ASCII文本文件。该文件包含2种类型的上下文:
Necessary Context: One which should be present at least once in its exact position.
Optional Context: One which may or may not be present, but if present should hold its proper place.
文件的详细外观:
[INDEX] <-- optional context, but if present should be the first context immediately followed by [FEATURE_ID], else file invalid
[FEATURE_ID] <-- necessary context and should always be immediately followed by [FEATURE_REV], else file is invalid. If [INDEX] context there then this should be the second CONTEXT in file else first.
[FEATURE_REV] <-- necessary context (must exist one per FEATURE_ID) and should always be immediately after [FEATURE_ID], else file is invalid.
[PRL_ID] <-- optional context, but if present should always be immediately after [FEATURE_REV], else file invalid
[NO_OF_BYTES] <--optional context, but if present, should always be immediately after [PRL_ID] if it is present, else immediately after [FEATURE_REV] if [PRL_ID] not present. Otherwise file invalid.
[NO_OF_SIGNIF_BITS] <-- optional context, but if present should always be between [NO_OF_BYTES] ( can be only present if [NO_OF_BYTES] present else not) and [CRC], else file invalid
[CRC] <-- necessary context,(must exist one per FEATURE_ID and FEATURE_REV). This is always the last context.
注意,有效文件中可能有多个[FEATURE_ID]上下文,并且在所有情况下,引导和跟随它的其他上下文应遵循相同的位置保持规则。像这样:
Validfile_1:
[FEATURE_ID]
[FEATURE_REV]
[CRC]
[INDEX]
[FEATURE_ID]
[FEATURE_REV]
[CRC]
Validfile_2:
[FEATURE_ID]
[FEATURE_REV]
[NO_OF_BYTES]
[CRC]
[INDEX]
[FEATURE_ID]
[FEATURE_REV]
[PRL_ID]
[NO_OF_BYTES]
[NO_OF_SIGNIF_BITS]
[CRC]
Validfile_3
[FEATURE_ID]
[FEATURE_REV]
[CRC]
Invalidfile_1 (order of contexts not ok):
[FEATURE_ID]
[INDEX]
[FEATURE_REV]
[NO_OF_BYTES]
[CRC]
[PRL_ID]
Invalidfile_2(FEATURE_REV or CRC can never exist without a FEATURE_ID):
[FEATURE_REV]
[NO_OF_BYTES]
[CRC]
Invalidfile_3 ( NO_OF_SIGNIF_BITS cannot exist without NO_OF_BYTES)
[FEATURE_ID]
[FEATURE_REV]
[NO_OF_SIGNIF_BITS]
[CRC]
我试图通过多个if else语句和egreps
在linux脚本中实现这一点,但代码行变得越来越复杂。
我要去的代码:
f_id_c=`egrep "[ ]*\[FEATURE_ID=[0-9].*\][ ]*" $1 | wc -l`
f_rev_c=`egrep "[ ]*\[FEATURE_REV=[0-9].*\][ ]*" $1 | wc -l`
crc_c=`egrep "[ ]*\[CRC\][ ]*" $1 | wc -l`
[[ $((f_id_c)) -eq 0 ]] && { echo "Invalid! No [FEATURE_ID=] context defined in profile file !"; exit 1; }
[[ $((f_rev_c)) -ne $((f_id_c)) ]] && { echo "Invalid! Not all [FEATURE_REV=] contexts have leading [FEATURE_ID=] defined"; exit 1; }
[[ $((crc_c)) -ne $((f_id_c)) ]] && { echo "Invalid! Not all [CRC] contexts have leading [FEATURE_ID=] defined"; exit 1; }
for (i=0;i<f_id_c;i++)
do
// Have a check with SED that will confirm there is a [FEATURE_REV=] immediately following [FEATURE_ID=]
done
有人可以建议进行紧凑的awk script
或sed
操作,以便我可以完成上述所有验证。
答案 0 :(得分:2)
你想要一个像这样的FSM:
$ cat tst.awk
BEGIN {
# define the allowed state transitions
ns["IDLE","INDEX"]
ns["IDLE","FEATURE_ID"]
ns["INDEX","FEATURE_ID"]
ns["FEATURE_ID","FEATURE_REV"]
ns["FEATURE_REV","PRL_ID"]
ns["FEATURE_REV","NO_OF_BYTES"]
ns["FEATURE_REV","CRC"]
ns["PRL_ID","NO_OF_BYTES"]
ns["PRL_ID","CRC"]
ns["NO_OF_BYTES","NO_OF_SIGNIF_BITS"]
ns["NO_OF_BYTES","CRC"]
ns["NO_OF_SIGNIF_BITS","CRC"]
ns["CRC","INDEX"]
ns["CRC","FEATURE_ID"]
# create a regexp of the state names for use in match()
for (state in ns) {
sub(SUBSEP".*","",state)
if (!seen[state]++) {
states = states (states ? "|" : "") state
}
}
# set the initial state
state = "IDLE"
}
# parse the input
match($0,states) {
nextState = substr($0,RSTART,RLENGTH)
if ( ! ((state,nextState) in ns) ) {
print "ERROR", NR, state, nextState, $0 | "cat>&2"
exit 1
}
state = nextState
}
针对发布的示例输入文件运行时:
$ cat file
....
[FEATURE_ID]
[FEATURE_REV]
...
...
[CRC]
[INDEX]
[FEATURE_ID]
[FEATURE_REV]
...
...
...
[CRC]
$
$ awk -f tst.awk file
$
它没有产生任何输出,正如预期的那样,因为您提供的样本没有包含任何错误,无法找到它。