===问题陈述=== 考虑到 PIC 格式的所有不同数据类型,从 Cobol Copybook 中提取数据长度(而不是字节)和精度的代码
这段代码足以处理 PIC 数据的所有情况吗?请问还有其他格式吗?
===代码正在处理的情况列表===
PIC X(n):从格式“PIC X(n)”中提取长度,其中 n 是字符数。 PIC 9(n):从格式“PIC 9(n)”中提取长度和整数长度,其中 n 是位数。 PIC 9(n)V9(m):从格式“PIC 9(n)V9(m)”中提取长度、整数长度和精度,其中 n 是整数位数,m 是小数位数。 PIC -9(n).99:从格式“PIC -9(n).99”中提取长度、整数长度和精度,其中 n 是整数位数。 PIC 9(n).99:从格式“PIC 9(n).99”中提取长度、整数长度和精度,其中 n 是整数位数。 PIC -9(n).9(m):从格式“PIC -9(n).9(m)”中提取长度、整数长度和精度,其中 n 是整数位数,m 是整数位数小数位。 PIC 9(n).9(m):从格式“PIC 9(n).9(m)”中提取长度、整数长度和精度,其中 n 是整数位数,m 是小数位数。 PIC 9(n) OCCURS m TIMES:从格式“PIC 9(n) OCCURS m TIMES”中提取长度和整数长度,其中 n 是位数,m 是字段出现的次数。 简单数据类型:PIC A、PIC 9:将简单数据类型的长度设置为 1。
=== PowerShell 代码===
$copybookDataType = "PIC 9(09)V99."
$totalLength = ""
$integerLength = "N/A"
$precision = "N/A"
# 1. Handling format: PIC X(n).
if ($copybookDataType -match "^PIC\s+X\((\d+)\).$") {
$totalLength = $Matches[1]
}
# 2. Handling format: PIC 9(n).
elseif ($copybookDataType -match "^PIC\s+(\d+)\((\d+)\).$") {
$totalLength = $Matches[2]
$integerLength = $Matches[1]
}
# 3. Handling format: PIC 9(09)V99.
elseif ($copybookDataType -match "^PIC\s+9\((\d+)\)V(\d+)\.$") {
$integerLength = $Matches[1]
$precision = ($Matches[2] -split "9").Count
$totalLength = $integerLength + $precision + 1
}
# 4. Handling format: PIC -9(n).
elseif ($copybookDataType -match "^PIC\s+-9\((\d+)\).$") {
$integerLength = $Matches[1]
$totalLength = $integerLength + 1
}
# 5. Handling format: PIC 9(n)V9(m).
elseif ($copybookDataType -match "^PIC\s+(\d+)\(\d+V(\d+)\).$") {
$integerLength = $Matches[1]
$precision = $Matches[2]
$totalLength = $integerLength + $precision + 1
}
# 6. Handling format: PIC -9(n).99.
elseif ($copybookDataType -match "^PIC\s+-9\((\d+)\)\.(\d+).$") {
$integerLength = $Matches[1]
$precision = ($Matches[2] -split "9").Count
if ($copybookDataType -match "\.$") {
$precision -= 1
}
$totalLength = $integerLength + $precision + 3
}
# 7. Handling format: PIC 9(n).99.
elseif ($copybookDataType -match "^PIC\s+9\((\d+)\)\.(\d+).$") {
$integerLength = $Matches[1]
$precision = ($Matches[2] -split "9").Count
if ($copybookDataType -match "\.$") {
$precision -= 1
}
$totalLength = $integerLength + $precision + 2
}
# 8. Handling format: PIC -9(n).9(m).
elseif ($copybookDataType -match "^PIC\s+-9\((\d+)\)\.9\((\d+)\).$") {
$integerLength = $Matches[1]
$precision = $Matches[2]
if ($copybookDataType -match "\.$") {
$precision -= 1
}
$totalLength = $integerLength + $precision + 4
}
# 9. Handling format: PIC 9(n).9(m).
elseif ($copybookDataType -match "^PIC\s+9\((\d+)\)\.9\((\d+)\).$") {
$integerLength = $Matches[1]
$precision = $Matches[2]
if ($copybookDataType -match "\.$") {
$precision -= 1
}
$totalLength = $integerLength + $precision + 3
}
# 10. Handling format: PIC 9(n) OCCURS m TIMES.
elseif ($copybookDataType -match "^PIC\s+(\d+)\(\d+\)\s+OCCURS\s+(\d+)\s+TIMES.$") {
$dataTypeLength = $Matches[1]
$occursTimes = $Matches[2]
$totalLength = $dataTypeLength * $occursTimes
$integerLength = $dataTypeLength
}
# 11. Handling simple data types: PIC A, PIC 9.
elseif ($copybookDataType -match "^PIC\s+(\w+).$") {
$totalLength = 1
}
# 12. Handling format: PIC .9(n).
elseif ($copybookDataType -match "^PIC\s+\.9\((\d+)\).$") {
$precision = $Matches[1]
$totalLength = $precision + 1
}
# 13. Handling format: PIC -.9(n).
elseif ($copybookDataType -match "^PIC\s+-\.9\((\d+)\).$") {
$precision = $Matches[1]
$totalLength = $precision + 2
}
Write-Host "Total Length: $totalLength"
Write-Host "Integer Length: $integerLength"
Write-Host "Precision: $precision"
问题:这段代码足以处理 PIC 数据的所有情况吗? 答案:不,由于某些原因(主要是关于格式)请参阅评论。
主要问题是根据COBOL规则无法正确匹配,因为你至少需要添加记录并考虑任何地方的换行符和注释;理论上,还有单词延续(很少使用)、条件编译(更常用)、
COPY REPLACING
/ REPLACE
以及使用可能在抄本之外定义的常量,甚至使用指定的编译选项。
另外:对于某些USAGE
,不同的编译器将使用不同的大小(并且SYNCHRONIZED
也可能由于填充而改变记录的大小,每个编译器/环境/选项也不同)。
结论:虽然您可以在 powershell 中解析某些内容 - 但它很可能不应该是 COBOL 抄写本。 要么变得更加复杂,因为您需要“解析 COBOL”(整个编译单元,而不仅仅是单个副本)并且特定于编译器/环境,或者仅可用于“简单”输入。
最合理的做法是将编译单元放入生成符号列表的 COBOL 编译器中(大多数编译器都有一个选项,也只能进行语法检查),然后解析该符号列表(其中包括使用的实际长度) )使用 powershell(也可以使用管道完成,不需要临时文件)。
举个例子:对于 GnuCOBOL,它会类似于cobc $yourflags_like_dialect_and_copybook_directories -fsyntax-only -frelax-syntax -w -t sym.lst --tlines=0 -fno-tsource -ftsymbols source.cob
(如果您希望结果出现在标准输出上,请使用
-
作为输出名称,而不是
sym.lst
)。