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

时间:2018-07-18 14:31:18

标签: perl awk sed

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

可以举例说明使用DELETE FROM yourTable WHERE ts_column < UNIX_TIMESTAMP() - (24*60*60); ,但是这种情况不应被认为是详尽无遗的,例如,可能希望包含带有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中的命令捕获标准输出。

我在核心实用程序中要求的是什么?

4 个答案:

答案 0 :(得分:3)

用数字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 中的正则表达式的match运算符返回匹配项,而/g modifier则找到所有匹配项。该列表将传递给map,后者将其主体中的代码应用于每个元素并返回结果列表。 qx is the operator的反引号形式,它返回命令的输出,这似乎是您想要的。

我将输出的格式留给您,在此列表由, 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

这一次处理一行输入。

更简单地说,在每个数字匹配时调用程序factor

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

借助{em}标量上下文中的while修饰符,处于/g条件的正则表达式在每次迭代中都从上一个匹配的位置继续寻找匹配项 。然后,在体内,$1中的每个捕获的匹配项都可以满足您的需求。


首次使用/g时的列表上下文 由于map采用列表作为输入而被强加。在第二个上下文中,上下文为标量,因为while条件中的代码被评估为标量。

答案 1 :(得分:2)

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

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的输出在末尾有换行符。

答案 2 :(得分:2)

awk命令输出中的1来自您打印system()的返回码。 system()返回它所调用命令的退出状态,而不是命令的输出-只是进入标准输出。另外,使用您使用的语法,在gensub()之前调用system(),因此您要使用文字字符串\\1调用factor。

使用GNU awk要做的正确语法:

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

这是可以与任何awk一起使用的吗?

$ 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.

并且使用GNU awk作为split()的第四个参数,可以写为:

$ 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.

答案 3 :(得分:1)

这可能对您有用(GNU sed):

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

通过内联函数调用将所有数字括起来,然后用双引号将整个字符串括起来,并使用echo对该字符串求值。