代码之家  ›  专栏  ›  技术社区  ›  Yimin Rong

使用自定义实用程序进行搜索和替换以进行转换

  •  3
  • Yimin Rong  · 技术社区  · 7 年前

    我想为匹配正则表达式的值运行自定义替换实用程序。这意味着对于正则表达式的每一个匹配项,调用包含匹配项字符的自定义实用程序。自定义实用程序的输出将替换原始字符。

    可以用举例说明 factor ,但这种情况不应被认为是详尽的,例如,可能希望将表达式包含在 $ , % 和算术运算符:

    $ factor 230
    230: 2 5 23
    

    使用此实用程序并为输入中的所有整数调用它,这是一个示例输入和输出:

    $ [code] <<< 'Given these numbers: 27, 13, 230, and 19, it is evident which are primes.'
    Given these numbers: 27: 3 3 3, 13: 13, 230: 2 5 23, and 19: 19, it is evident which are primes.
    

    我认为这可能有效,但看起来它试图直接解释输入。使用 sed (GNU sed) 4.2.2 .

    $ sed -E 's/([0-9]+)/factor \1/ge' <<< 'Given these numbers: 27, 13, 230, and 19, it is evident which are primes.'
    sh: 1: Given: not found
    

    显然我不明白 e 标志为。我试过这么做 awk :

    $ awk '{r = gensub(/([0-9]+)/, system("factor \\1"), "g"); print r}' <<< 'Given the numbers with factors: 27, 13, 230, and 19, it is evident which are primes.'
    1:
    Given the numbers with factors: 0, 0, 0, and 0, it is evident which are primes.
    

    我不确定 1: 来自,但很明显它只打印来自的返回代码 system . 似乎没有方法从中的命令捕获标准输出。 AWK .

    我所要求的在核心实用程序中是可能的吗?

    4 回复  |  直到 7 年前
        1
  •  2
  •   Ed Morton    7 年前

    这个 1 在awk命令中,输出来自打印返回代码的 system() . 系统() 返回它调用的命令的退出状态,而不是命令的输出-它只会进入stdout。另外,使用所使用的语法,在gensub()之前调用system(),所以使用文本字符串调用factor \\1 .

    使用gnu awk执行所尝试操作的正确语法:

    awk '{r = gensub(/([0-9]+)/, system("factor \\1"), "g"); print r}'
    

    这是否适用于任何锥子:

    $ awk '{
        head = ""
        while ( match($0,/[0-9]+/) ) {
            cmd = "factor " substr($0,RSTART,RLENGTH)
            ret = ( (cmd | getline line) > 0 ? line : cmd " failed" )
            close(cmd)
            head = head substr($0,1,RSTART-1) ret
            $0 = substr($0,RSTART+RLENGTH)
        }
        $0 = head $0
        print
    }' <<< 'Given these numbers: 27, 13, 230, and 19, it is evident which are primes.'
    Given these numbers: 27: 3 3 3, 13: 13, 230: 2 5 23, and 19: 19, it is evident which are primes.
    

    对于第四个arg to split()的gnu awk,它可以写为:

    $ awk '{
        n = split($0,others,/[0-9]+/,nums)
        $0 = ""
        for (i=1; i<n; i++) {
            cmd = "factor " nums[i]
            ret = ( (cmd | getline line) > 0 ? line : cmd " failed" )
            close(cmd)
            $0 = $0 others[i] ret
        }
        $0 = $0 others[n]
        print
    }' <<< 'Given these numbers: 27, 13, 230, and 19, it is evident which are primes.'
    Given these numbers: 27: 3 3 3, 13: 13, 230: 2 5 23, and 19: 19, it is evident which are primes.
    
        2
  •  3
  •   zdim    7 年前

    将数字替换为 factor 在每个

    echo "Given these numbers: 27, 13, 230, and 19, it is evident which are primes." | 
        perl -wnE'say s{([0-9]+)}{$f=qx(factor $1); chomp $f; $f}egr'
    

    这使用 /e 修饰符,将替换端作为代码进行计算。这个 qx 运行命令并返回其输出,换行符将从该输出中删除。 chomp . 用 /g 它不断地遍历字符串以替换所有数字。解释见下文。

    /r 修改替换运算符 s/// 返回修改后的字符串。

    输出:

    Given these numbers: 27: 3 3 3, 13: 13, 230: 2 5 23, and 19: 19, it is evident which are primes.
    

    在其他方法的背景下,继续阅读以获取解释。


    原岗位

    例如,从输入行中提取数字并对其上的每一行调用程序

    echo "Given these numbers: 27, 13, 230, and 19, it is evident which are primes."
        | perl -wnE'say "Result: ", join(",", map { qx(factor $_) } /([0-9]+)/g)'
    

    正则表达式中的匹配运算符 列表 context 小精灵 返回匹配项,而 /g modifier 让它找到所有这些。该列表将传递给 map 将其主体中的代码应用于每个元素并返回结果列表。 这个 qx is the operator backticks的形式,它返回命令的输出,这似乎是您想要的。

    我把输出的格式留给您,这是列表 join -ED , 并以一根绳子作为前缀。

    如果输入行在文件中

    perl -wnE'say "Result: ", join(",", map { qx(factor $_) } /([0-9]+)/g)' file
    

    对于更复杂的处理,可以将匹配列表分配给数组 然后做你想做的事

    perl -wnE'@n = /([0-9]+)/g; for (@n) { say "process $_" }' file
    

    一次处理一行输入。

    更简单地说,调用程序 因素 在每个匹配的数字上

    perl -wnE'while (/([0-9]+)/g) { say qx(factor $1) }' file
    

    中的正则表达式 while 条件在每个迭代中不断地查找匹配项,从上一个匹配的位置继续,其优点是 g 中的修饰符 纯量的情境 小精灵 . 在身体内部,你可以做你所需要的每一个捕捉到的比赛,这是在 $1 .


    小精灵 第一次使用的列表上下文 g 是自 map 将列表作为输入。在第二种情况下,上下文是标量的,因为 虽然 条件的计算结果为标量。

        3
  •  2
  •   beasy    7 年前

    以下是替换字符串中文本的解决方案:

    perl -MList::Util=pairs -E '($m,$s) = ($_->key,$_->value) and $ARGV[0] =~ s/$m/$s/ for pairs map {$_, qx/factor $_/} $ARGV[0] =~ /(\d+)/g; say $ARGV[0]' \
    'Given these numbers: 27, 13, 230, and 19, it is evident which are primes'
    

    注意,输出 factor 结尾有新行。

        4
  •  1
  •   potong    7 年前

    这可能适用于您(GNU SED):

    sed 's/[0-9]\+/$(factor &)/g;s/.*/echo "&"/e' file
    

    用内联函数调用将所有数字括起来,然后用双引号将整个字符串括起来,并使用 echo .

    推荐文章