AWK-使用count变量的脚本出错,还是AWK实现/版本出错? Awk版本:GNU Awk 3.1.1 平台:OpenVMS 8.4-L1 Awk知识:有限

AWK-使用count变量的脚本出错,还是AWK实现/版本出错? Awk版本:GNU Awk 3.1.1 平台:OpenVMS 8.4-L1 Awk知识:有限,awk,gnu,openvms,Awk,Gnu,Openvms,脚本(Awk一行)。 注意: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;

脚本(Awk一行)。 注意: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
我想知道的是

  • 其他使用不同平台的人是否可以测试它以查看它是否产生相同的输出
  • 是我正在运行的awk版本出了问题,还是我的awk脚本有什么我不理解的地方
  • 在我看来,它确实应该生成一个file.log;1999 file.log;1行,但它没有。我不知所措,需要一些指导/awk教育


    提前感谢:-)

    ”;”“这就是问题所在。试试看。”开始$1“;”x。。。相反你发布的内容相当于。打印$0,$1;x} 也就是说,扔掉x。Hth

    为了了解发生了什么,您可以添加额外的输出

    $ 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
    的值将用作调用block
    {something}
    的条件

    在第一行的步骤1中,
    x++
    将返回0并递增“x”,这将跳过步骤2。但在步骤3中,x将是1

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

    您可以这样修复它:

    gawk -F\; 'BEGIN {x = 0} {print $0,$1";"++x}' in.file
    

    您需要使用
    ++x
    代替
    x++
    x++
    最初计算结果为
    0
    (但将
    x
    增加为1),0为false,因此不执行操作;第一行不打印任何内容

    当您将
    x
    初始化为
    -1
    时,会打印第一行,因为
    x++
    的计算结果为
    -1
    ,这是真的;第二个被跳过,因为
    x
    为0,以此类推

    您不需要开始块。变量以零(或空字符串)作为值自动激活。事实上,您不需要根据
    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
    

    既然您对AWK不太了解,我可以建议您完全跳过它,转而使用PERL吗

    但首先要做的是。你到底想解决什么问题? 在我看来,您获得了一个文件名列表(DIR/COL=2/OUT=x.x) 您希望使用该列表生成一个重命名,其中版本号最高的文件变为1号,下一个变为2号,依此类推。 对吗

    我希望没有必要担心重叠,也许是因为有了版本限制

    DCL默认值可以很好地做到这一点。 -在这里使用PERL只是一种创建一组文件的简便方法 -使用文件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)
    
    $dir/文件
    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(){$i++;$old=$\s/;\d++/;$i/;重命名$old,$\u}”
    $dir/文件
    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
    
    =glob(“xxx”)=glob(qq(xxx)=带内插字符串的通配符查找。
    对于()#循环所有匹配模式的文件,输出到$_
    {#代码块
    每次迭代的$i++#增量。从1开始
    $old=$\u;#保存获取的文件名
    s/;\d+/;$i/;#用数字替换分号
    重命名$old,$#实际重命名。请先尝试打印。
    }#代码块末尾
    

    好吗?

    我想您会发现,VMS用于转义双引号的命令行约定是将双引号加倍,而不是像在Unix上那样使用反斜杠。我不知道这一点,但如果您将
    序列视为将分号输入输出的一种方式,它是有意义的。不幸的是,OpenVMS命令行需要“;”要输出一个引号,如果我返回到单引号,输出不包括;和x的值(即,我得到.log而不是.log;1等)。输出正常,除非x变为1,因为某种原因,它工作得很好-谢谢:-)我确实尝试过使用++x的东西(尽管我使用了x++)但是我无法正确理解语法,我非常感谢您的帮助。我将尝试您列出的不同组合,希望能够巩固它的工作原理。很明显,我对awk的新手理解是因为您的解决方案也非常优雅:-)