如何使用 awk 在单词中间插入内容?

How can I use awk to insert something in the middle of the word?

我有一个输入:

This is a test

我想在单词中间插入一些字母,比如:

This is a teSOMETHINGst

我知道我可以通过 $i 定义所需的词,但我怎样才能那样修改词?

我正在尝试这样做:

{
    i=4 # finding somehow
    print (substr($i,1,(length($i)/2)) "SOMETHING" substr($i,(length($i)/2),(length($i)/2)))
}

因为我是 awk 的新手,我想知道这是否是正确的方法。

假设您的要求是匹配包含 test 的列号并对其进行一些操作,对直到 NF 的列进行简单循环并使用正则表达式匹配运算符 [=13] 进行匹配=] 或对于固定字符串进行相等匹配 $i == "test"

awk '
{
  for(i=1;i<=NF;i++) {
    if ($i ~ "test") {
      halfLength=(length($i)/2)
      $i=(substr($i,1,halfLength) "SOMETHING" substr($i,(halfLength+1),halfLength))
    }
  }
}1' <<<"This is a test"

这会产生预期的输出。请注意,我已调用 substr() 将字符串的第二部分打印为 substr($i,(halfLength+1),halfLength)。您之前错过的 +1 是必需的。我使用 substr() 结果修改包含 test 的列号,即 $i=..

此外,在执行 {..}1 时,每个列字段都会根据修改(如果有)进行重构,在我们的例子中,仅包含您想要的字符串的列。

另请注意,如果目标字符串包含奇数个字符或构成另一个较大字符串的子字符串(可以使用相等运算符但正则表达式方法会失败),则整个尝试将失败

这可能是您要查找的内容:

$ awk 'match([=10=],/\<test\>/){mid=int(RLENGTH/2); [=10=]=substr([=10=],RSTART,mid) "SOMETHING" substr([=10=],RSTART+mid,RELNGTH-mid)} 1'

例如一些测试用例(没有双关语意):

$ echo 'This is a test' |
awk 'match([=11=],/\<test\>/){mid=int(RLENGTH/2); [=11=]=substr([=11=],RSTART,mid) "SOMETHING" substr([=11=],RSTART+mid,RLENGTH-mid)} 1'
teSOMETHINGst

$ echo 'These are tests' |
awk 'match([=11=],/\<tests\>/){mid=int(RLENGTH/2); [=11=]=substr([=11=],RSTART,mid) "SOMETHING" substr([=11=],RSTART+mid,RLENGTH-mid)} 1'
teSOMETHINGsts

$ echo 'These contestants are in a test' |
awk 'match([=11=],/\<test\>/){mid=int(RLENGTH/2); [=11=]=substr([=11=],RSTART,mid) "SOMETHING" substr([=11=],RSTART+mid,RLENGTH-mid)} 1'
teSOMETHINGst

另一个从好奇心发展为个人仇恨的人 (:

$ echo This is a contestant test | 
awk -v s="test" '
BEGIN {
    FS=OFS=""
}
{
    if(i=match([=10=], "(^| )" s "( |$)")) {   # match over index since regex support
        j=(i+length(s)/2+!!(i-1))          # !!(i-1) detect beginning of record
        $j="SOMETHING" $j
    }
}1'
This is a contestant teSOMETHINGst

另一个使用空分隔符,主要是为了满足个人好奇心:

$ echo This is a test | 
awk -v s="test" '
BEGIN {
    FS=OFS=""                # empty separators
}
{
    if(i=index([=11=],s)) {      # index finds the beginning of test
        j=(i+length(s)/2)    # midpoint
        $j="SOMETHING" $j    # insert string
    }
}1'                          # output
This is a teSOMETHINGst