【问题标题】:How to write to a file using awk to find a string in between ( ); and add a printline after ; to print the string found?如何使用 awk 写入文件以在 ( ) 之间查找字符串;并在 ; 之后添加一个打印行打印找到的字符串?
【发布时间】:2013-12-20 09:15:57
【问题描述】:

我在一个文件夹中有一些文件,其中有几个 sqrt(x+y);职能。我想找出 x+y 中的内容。所以我想读取 sqrt(x+y ); 里面的值并添加一个 printf(x+y );在分号之后。我尝试了大约一个月。但还是找不到办法。

请帮忙。如果您知道我在哪里可以找到有关 AWK 的任何好的教程或书籍,请告诉我.. 谢谢。 以下是我想出的算法。 (我对 AWK 完全陌生)

循环遍历所有文件{ 如果一行以 sqrt( 开始将字符串放入变量 a / 或数组 a 直到找到); 写 Print ( , concatenate, 然后是 value , concatenate,); 在下一行。

【问题讨论】:

  • 为什么不发布一些示例数据和预期输出?

标签: shell unix sed awk pattern-matching


【解决方案1】:

awk 确实是一个很好的工具,但为什么不扩展一下呢?如果您愿意丢弃括号内的空格,请尝试:

cat << 'EOF' - input-file | m4
divert(-1)
define(`sqrt',`divert(1)'$1
`divert(-1)')
EOF

这应该打印出在名为input-file 的文件中对sqrt 的调用中出现的每个字符串。这不会评估字符串,但我不清楚你是否想要。

此解决方案的主要优点是它可以很好地处理嵌套括号。也就是说,sqrt( foo( bar( x + y ))) 形式的行将正确打印foo( bar( x + y )),而awk 将难以正确解析。主要缺点是它需要正确的输入语法(不平衡的括号会导致问题)。

【讨论】:

    【解决方案2】:

    您可以尝试以下 bash 脚本:

    #! /bin/bash
    
    files=(*.txt)
    
    for ((i=0; i<${#files[@]}; i++)) ; do
        file="${files[$i]}"
        awk -f f.awk "$file" > "${file}.mod"
    done
    

    f.awk 在哪里:

    {
        gsub(/\([^)]*\)/,"&; printf&")
        print
    }
    

    请注意,这不适用于嵌套括号,例如 sqrt(4+2*(x+y))..(如果需要,我可以尝试更新我的答案。)。

    给定示例文件input.txt:

    x=7;
    sqrt(x+5*4); sqrt(x*x); 
    i=3;
    a=2+sqrt(8);
    

    运行:awk -f f.awk input.txt 给出:

    x=7;
    sqrt(x+5*4); printf(x+5*4); sqrt(x*x); printf(x*x); 
    i=3;
    a=2+sqrt(8); printf(8);
    

    对于 Gnu awk,我推荐以下 awk 资源:http://www.gnu.org/software/gawk/manual/gawk.html

    【讨论】:

    • 非常清楚,感谢您的链接。我需要运行它以将 print() 添加到目录中带有 sqrt 的所有文件中。它里面有一些括号。我给出了命令 awk -f f.awk input.txt>>output.txt 将其写入不同的文件;但我希望它在同一个文件中而不是在 output.txt 中。这就是我花了很长时间才做到这一点的原因
    • @MadHatter 谢谢。如果您希望它在同一个文件中,您可以先将 input.txt 移动到例如input.txt.bak 然后做awk -f f.awk input.txt.bak &gt; input.txt.. 你需要像sqrt(4+2(x+y)) 这样的嵌套括号支持吗?
    • 谢谢,我使用了一个 shell 脚本来运行你提供的 f.awk 脚本,它工作正常。如果我想输出 sqrt(x);打印 , "x" 而不是 sqrt(x);printf(x);我应该如何更改这个 awk 脚本?我改变了 f.awk 如下: gsub(/sqrt([^)]*\"/,"&; print,\"&") 但这仍然会打印括号。你如何在这里用“”替换括号。 [^)]*\" 部分的含义我还不清楚。
    • @MadHatter 嗨!尝试将f.awk 替换为{ print gensub(/\(([^)]*)\)/,"&amp;, print \"\\1\"","g")}..
    • @MadHatt \([^)]*\) 的含义: 1) 匹配左括号:\(。 2. 匹配任何不是右括号的字符:[^)]。 3. 尽可能多地重复第 2 条:*。 4.匹配右括号:\).
    猜你喜欢
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    • 2015-01-17
    • 1970-01-01
    相关资源
    最近更新 更多