AWK - 带有计数变量的脚本中的错误或AWK实现/版本中的错误?

时间:2017-03-31 04:26:02

标签: awk gnu openvms

  • Awk版本:GNU Awk 3.1.1
  • 平台:OpenVMS 8.4-L1
  • Awk知识:有限

脚本(Awk one liner)。 注意:OpenVMS参数解析需要引号

gawk "-F" ";" "BEGIN {x = 0} ; x++ {print $0,$1"";""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

我想知道的是

  1. 使用其他平台的其他人是否可以对此进行测试以查看它是否产生相同的输出?
  2. 可能是我正在运行的awk版本有问题或者我的awk脚本有什么问题我不理解
  3. 在我看来它应该产生一个file.log; 1999 file.log; 1行,但它没有。我不知所措,需要一些指导/ awk教育

    提前致谢: - )

4 个答案:

答案 0 :(得分:2)

您需要使用++x代替x++x++最初评估为0(但将x增加为1),0为false,因此不采取行动;第一行没有打印任何内容。

x初始化为-1时,会打印第一行,因为x++评估为-1,这是真的;第二个被跳过,因为x为0,等等。

您不需要BEGIN块。变量是自动生成的,零(或空字符串)作为值。事实上,您不需要根据x是否为零来触发打印;您只想始终打印增量值x

所以,在Mac(类Unix系统)系统上,我可以运行:

$ gawk "-F" ";" '{print $0,$1";"++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 $0,$1"";""++x}" file.in

答案 1 :(得分:1)

为了理解发生了什么,你可以增加额外的输出。

<App>
   <input1 />
   <input2 />
</App>

因此有后增量的效果。

$ gawk -F\; 'BEGIN {x = 0} {print "step 1: "x} x++ {print "step 2: "x; print $0,$1";"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 x {something}相同。因此,{if(x){something}}的值将用作调用块x的条件。

在第一行,在第1步,{something}将返回0并递增'x',这将跳过第2步。但在第3步'x'将为1.

在第二行,在第1步,x++将返回1并递增'x'。在第2步,x将已经是'2'。这就是你得到的。

你可以这样解决:

x++

答案 2 :(得分:0)

“”;“”是问题所在。尝试。 '开始... $ 1“;”x ......相反。你发布的内容相当于。打印$ 0,$ 1; x} I.e.扔x偏。 HTH

答案 3 :(得分:0)

由于你不太了解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

OK?