AWK - 带有计数变量的脚本错误或 AWK 实现/版本错误?
AWK - error in script with count variable OR error in AWK Implementation / version?
- Awk 版本:GNU Awk 3.1.1
- 平台:OpenVMS 8.4-L1
- awk知识:有限
脚本(Awk 一行)。
注意:OpenVMS 参数解析需要引号
gawk "-F" ";" "BEGIN {x = 0} ; x++ {print [=10=],"";""x}" in.file > out.file
**in.file**
file.log;2000
file.log;1999
file.log;1998
file.log;1997
**out.file**
file.log;1999 file.log;2
file.log;1998 file.log;3
file.log;1997 file.log;4
我想要以下内容
file.log;2000 file.log;1
file.log;1999 file.log;2
file.log;1998 file.log;3
file.log;1997 file.log;4
如果我将上面的 awk 命令更改为:...{x = -1}... 我得到
**out.file**
file.log;2000 file.log;0
file.log;1998 file.log;2
file.log;1997 file.log;3
我想知道的是
- 其他人是否可以使用不同的平台测试它是否产生相同的输出?
- 可能是我的 awk 版本有问题 运行 或者我的 awk 脚本有什么问题我不理解
在我看来它确实应该产生 file.log;1999 file.log;1 行,但它没有。我不知所措,需要一些指导/awk 教育
提前致谢:-)
"";"" 是问题所在。尝试。 'BEGIN ... $1";"x ... 代替。您发布的内容相当于。打印 $0,$1; x}即扔掉 x。 Hth
为了了解发生了什么,您可以添加额外的输出。
$ gawk -F\; 'BEGIN {x = 0} {print "step 1: "x} x++ {print "step 2: "x; print [=10=],";"x} {print "step 3: "x"\n"}' in.file
step 1: 0
step 3: 1
step 1: 1
step 2: 2
file.log;1999 file.log;2
step 3: 2
step 1: 2
step 2: 3
file.log;1998 file.log;3
step 3: 3
step 1: 3
step 2: 4
file.log;1997 file.log;4
step 3: 4
所以有post增量的效果。
x {something}
等同于 {if(x){something}}
。因此 x
的值将用作调用块 {something}
.
的条件
在第一行,在第 1 步,x++
将 return 0 并递增 'x',这将跳过第 2 步。但是在第 3 步 'x' 将是1.
在第二行,在第 1 步,x++
将 return 1 并递增 'x'。在第 2 步中,x 已经是“2”。这就是你得到的。
你可以这样修复:
gawk -F\; 'BEGIN {x = 0} {print [=11=],";"++x}' in.file
您需要使用 ++x
代替 x++
。 x++
最初评估为 0
(但将 x
递增为 1),0 为假,因此不执行操作;第一行没有打印任何内容。
当您将 x
初始化为 -1
时,会打印第一行,因为 x++
的计算结果为 -1
为真;第二个被跳过,因为 x
是 0,等等
您不需要 BEGIN 块。变量以零(或空字符串)作为值自动激活。事实上,您不需要根据 x
是否为零来触发打印;您只是想始终打印 x
.
的增量值
所以,在 Mac(类 Unix)系统上,我可以 运行:
$ gawk "-F" ";" '{print [=10=],";"++x}' file.in
file.log;2000 file.log;1
file.log;1999 file.log;2
file.log;1998 file.log;3
file.log;1997 file.log;4
$
转换为 VMS 惯例,即:
gawk "-F" ";" "{print [=11=],"";""++x}" file.in
既然你不太了解 AWK,我可以建议完全跳过它并切换到 PERL 吗?
但要事第一。你真正想解决什么问题?
在我看来你获得了文件名列表(DIR/COL=2/OUT=x.x)
您希望使用该列表生成重命名,其中版本号最高的文件变为编号 1,下一个变为 2,依此类推。
对吗?
我希望没有必要担心重叠可能是因为版本限制。
DCL 默认值可以做到这一点。
- 在这里使用 PERL 作为创建一堆文件的便捷方式
- 使用 FILE_ID 显示哪个文件是哪个
开始了。
$perl -e "open X,qq(>file.log;$_) for 1997..2000"
$dir/file
FILE.LOG;2000 (59705,105,0)
FILE.LOG;1999 (46771,399,0)
FILE.LOG;1998 (42897,980,0)
FILE.LOG;1997 (24538,519,0)
$rena/log file.log.* tmp.log;
%RENAME-I-RENAMED, FILE.LOG;2000 renamed to TMP.LOG;1
%RENAME-I-RENAMED, FILE.LOG;1999 renamed to TMP.LOG;2
%RENAME-I-RENAMED, FILE.LOG;1998 renamed to TMP.LOG;3
%RENAME-I-RENAMED, FILE.LOG;1997 renamed to TMP.LOG;4
$rena tmp.log;* file.log/log
%RENAME-I-RENAMED, TMP.LOG;4 renamed to FILE.LOG;4
%RENAME-I-RENAMED, TMP.LOG;3 renamed to FILE.LOG;3
%RENAME-I-RENAMED, TMP.LOG;2 renamed to FILE.LOG;2
%RENAME-I-RENAMED, TMP.LOG;1 renamed to FILE.LOG;1
$dir/file file.log;*
FILE.LOG;4 (24538,519,0)
FILE.LOG;3 (42897,980,0)
FILE.LOG;2 (46771,399,0)
FILE.LOG;1 (59705,105,0)
好吗?不需要帮手。只有两个命令依赖于“;”停止继承的魔法。
现在让我们看看如何直接在 Perl 中执行此操作。
$ dir/file
FILE.LOG;2000 (59705,105,0)
FILE.LOG;1999 (46771,399,0)
FILE.LOG;1998 (42897,980,0)
FILE.LOG;1997 (24538,519,0)
$ perl -e "for (<file.log;*>) {$i++; $old = $_; s/;\d+/;$i/; rename $old, $_}"
$ dir/file
FILE.LOG;4 (24538,522,0)
FILE.LOG;3 (42897,983,0)
FILE.LOG;2 (46771,402,0)
FILE.LOG;1 (59705,108,0)
步骤细分:
<xxx> = glob("xxx") = glob(qq(xxx) = wildcard lookup with interpolated string.
for (<file.log;*>) # Loop over all files matching pattern, output into $_
{ # code block
$i++; # increment for each iteration. start at 1
$old = $_; # save the fetched file name
s/;\d+/;$i/; # substitute a semicolon followed by numbers
rename $old, $_ # Actual rename. Try with PRINT first.
} # end of code block
好吗?
- Awk 版本:GNU Awk 3.1.1
- 平台:OpenVMS 8.4-L1
- awk知识:有限
脚本(Awk 一行)。 注意:OpenVMS 参数解析需要引号
gawk "-F" ";" "BEGIN {x = 0} ; x++ {print [=10=],"";""x}" in.file > out.file
**in.file**
file.log;2000
file.log;1999
file.log;1998
file.log;1997
**out.file**
file.log;1999 file.log;2
file.log;1998 file.log;3
file.log;1997 file.log;4
我想要以下内容
file.log;2000 file.log;1
file.log;1999 file.log;2
file.log;1998 file.log;3
file.log;1997 file.log;4
如果我将上面的 awk 命令更改为:...{x = -1}... 我得到
**out.file**
file.log;2000 file.log;0
file.log;1998 file.log;2
file.log;1997 file.log;3
我想知道的是
- 其他人是否可以使用不同的平台测试它是否产生相同的输出?
- 可能是我的 awk 版本有问题 运行 或者我的 awk 脚本有什么问题我不理解
在我看来它确实应该产生 file.log;1999 file.log;1 行,但它没有。我不知所措,需要一些指导/awk 教育
提前致谢:-)
"";"" 是问题所在。尝试。 'BEGIN ... $1";"x ... 代替。您发布的内容相当于。打印 $0,$1; x}即扔掉 x。 Hth
为了了解发生了什么,您可以添加额外的输出。
$ gawk -F\; 'BEGIN {x = 0} {print "step 1: "x} x++ {print "step 2: "x; print [=10=],";"x} {print "step 3: "x"\n"}' in.file
step 1: 0
step 3: 1
step 1: 1
step 2: 2
file.log;1999 file.log;2
step 3: 2
step 1: 2
step 2: 3
file.log;1998 file.log;3
step 3: 3
step 1: 3
step 2: 4
file.log;1997 file.log;4
step 3: 4
所以有post增量的效果。
x {something}
等同于 {if(x){something}}
。因此 x
的值将用作调用块 {something}
.
在第一行,在第 1 步,x++
将 return 0 并递增 'x',这将跳过第 2 步。但是在第 3 步 'x' 将是1.
在第二行,在第 1 步,x++
将 return 1 并递增 'x'。在第 2 步中,x 已经是“2”。这就是你得到的。
你可以这样修复:
gawk -F\; 'BEGIN {x = 0} {print [=11=],";"++x}' in.file
您需要使用 ++x
代替 x++
。 x++
最初评估为 0
(但将 x
递增为 1),0 为假,因此不执行操作;第一行没有打印任何内容。
当您将 x
初始化为 -1
时,会打印第一行,因为 x++
的计算结果为 -1
为真;第二个被跳过,因为 x
是 0,等等
您不需要 BEGIN 块。变量以零(或空字符串)作为值自动激活。事实上,您不需要根据 x
是否为零来触发打印;您只是想始终打印 x
.
所以,在 Mac(类 Unix)系统上,我可以 运行:
$ gawk "-F" ";" '{print [=10=],";"++x}' file.in
file.log;2000 file.log;1
file.log;1999 file.log;2
file.log;1998 file.log;3
file.log;1997 file.log;4
$
转换为 VMS 惯例,即:
gawk "-F" ";" "{print [=11=],"";""++x}" file.in
既然你不太了解 AWK,我可以建议完全跳过它并切换到 PERL 吗?
但要事第一。你真正想解决什么问题? 在我看来你获得了文件名列表(DIR/COL=2/OUT=x.x) 您希望使用该列表生成重命名,其中版本号最高的文件变为编号 1,下一个变为 2,依此类推。 对吗?
我希望没有必要担心重叠可能是因为版本限制。
DCL 默认值可以做到这一点。 - 在这里使用 PERL 作为创建一堆文件的便捷方式 - 使用 FILE_ID 显示哪个文件是哪个 开始了。
$perl -e "open X,qq(>file.log;$_) for 1997..2000"
$dir/file
FILE.LOG;2000 (59705,105,0)
FILE.LOG;1999 (46771,399,0)
FILE.LOG;1998 (42897,980,0)
FILE.LOG;1997 (24538,519,0)
$rena/log file.log.* tmp.log;
%RENAME-I-RENAMED, FILE.LOG;2000 renamed to TMP.LOG;1
%RENAME-I-RENAMED, FILE.LOG;1999 renamed to TMP.LOG;2
%RENAME-I-RENAMED, FILE.LOG;1998 renamed to TMP.LOG;3
%RENAME-I-RENAMED, FILE.LOG;1997 renamed to TMP.LOG;4
$rena tmp.log;* file.log/log
%RENAME-I-RENAMED, TMP.LOG;4 renamed to FILE.LOG;4
%RENAME-I-RENAMED, TMP.LOG;3 renamed to FILE.LOG;3
%RENAME-I-RENAMED, TMP.LOG;2 renamed to FILE.LOG;2
%RENAME-I-RENAMED, TMP.LOG;1 renamed to FILE.LOG;1
$dir/file file.log;*
FILE.LOG;4 (24538,519,0)
FILE.LOG;3 (42897,980,0)
FILE.LOG;2 (46771,399,0)
FILE.LOG;1 (59705,105,0)
好吗?不需要帮手。只有两个命令依赖于“;”停止继承的魔法。
现在让我们看看如何直接在 Perl 中执行此操作。
$ dir/file
FILE.LOG;2000 (59705,105,0)
FILE.LOG;1999 (46771,399,0)
FILE.LOG;1998 (42897,980,0)
FILE.LOG;1997 (24538,519,0)
$ perl -e "for (<file.log;*>) {$i++; $old = $_; s/;\d+/;$i/; rename $old, $_}"
$ dir/file
FILE.LOG;4 (24538,522,0)
FILE.LOG;3 (42897,983,0)
FILE.LOG;2 (46771,402,0)
FILE.LOG;1 (59705,108,0)
步骤细分:
<xxx> = glob("xxx") = glob(qq(xxx) = wildcard lookup with interpolated string.
for (<file.log;*>) # Loop over all files matching pattern, output into $_
{ # code block
$i++; # increment for each iteration. start at 1
$old = $_; # save the fetched file name
s/;\d+/;$i/; # substitute a semicolon followed by numbers
rename $old, $_ # Actual rename. Try with PRINT first.
} # end of code block
好吗?