在awk中替换一个字符

huangapple go评论57阅读模式
英文:

Replacing a character in awk

问题

我正在使用以下命令对文件进行操作:

awk '{delta = $1 - avg; avg += delta / NR; mean2 += delta * ($1 - avg); } END { print avg" "sqrt(642)*sqrt(mean2 / NR); }' param_A_ratio_re_truncated.txt

现在,我想一次性重复执行此命令行,但将文件名中的“A”替换为“D、G、K、M”等其他字符,而不是每次都键入该行。虽然我可以替换文件名中的数值,但我不确定如何更改字符。任何建议将不胜感激。谢谢。

英文:

I am using the following command to do a manipulation on a file:

awk '{delta = $1 - avg; avg += delta / NR; mean2 += delta * ($1 - avg); } END { print avg" "sqrt(642)*sqrt(mean2 / NR); }' param_A_ratio_re_truncated.txt

Now, I want to repeat this command line at once but replace "A" in the file name with "D, G, K, M" etc. other than typing the line every time. While I can replace numerical values in a file name, I am not sure how to change a character. Any suggestions would be appreciated. Thank you.

答案1

得分: 5

你可以尝试:

awk '.....' param_[ADGKM]_ratio_re_truncated.txt

...但这将生成一个单一的平均值/平方根/均值输出(即,awk 脚本将处理所有文件作为一个大数据集)。

如果意图是为每个文件生成单独的平均值/平方根/均值,一个简单/快速的解决方案是:

for fname in param_[ADGKM]_ratio_re_truncated.txt
do
    echo "######### 输入:${fname}"
    awk '.....' "${fname}"
done

你可以使用单个 awk 脚本来处理所有文件 并且 为每个文件生成单独的平均值/平方根/均值,但这将需要更多的代码,例如:

function print_output() {
    if (rowcnt > 0)
        print FILENAME, avg, sqrt(642)*sqrt(mean2 / rowcnt)
    delta = avg = mean2 = ""
    rowcnt = 0
}

FNR==1 { print_output() }
       { rowcnt++
         delta = $1 - avg
         avg += delta / rowcnt
         mean2 += delta * ($1 - avg)
       } 
END    { print_output() }

注意:

  • 如果不想显示每个文件的名称,请删除 'FILENAME,'
  • 假设所有文件至少有一行输入,否则可能需要一些额外的逻辑来处理 '空' 文件。
  • 由于没有示例输入和预期输出,无法测试。
  • 我假设原作者的当前代码按预期工作(即,我没有尝试验证原作者的当前代码)。
英文:

You can try:

awk '.....' param_[ADGKM]_ratio_re_truncated.txt

... but this is going to generate a single avg/sqrt/mean output (ie, the awk script will process all files as one big set of data).

If the intention is to generate a separate avg/sqrt/mean for each file, one easy/quick solution:

for fname in param_[ADGKM]_ratio_re_truncated.txt
do
    echo "######### input: ${fname}"
    awk '.....' "${fname}"
done

You can use a single awk script to process all files and generate a separate avg/sqrt/mean for each file but it will require a bit more code, eg:

awk '
function print_output() {
    if (rowcnt > 0)
        print FILENAME, avg, sqrt(642)*sqrt(mean2 / rowcnt)
    delta = avg = mean2 = ""                          # reset variables for next file
    rowcnt = 0
}

FNR==1 { print_output() }                             # FNR==1 => new file so print results for previous file
       { rowcnt++
         delta = $1 - avg
         avg += delta / rowcnt
         mean2 += delta * ($1 - avg)
       } 
END    { print_output() }                             # print results for last file
' param_[ADGKM]_ratio_re_truncated.txt

NOTES:

  • remove 'FILENAME,' if you don't want to display each file's name
  • assumes all files have at least one line of input otherwise some additional logic may be needed to handle 'empty' files
  • unable to test since there's no sample input nor expected output
  • I'm assuming OP's current code works as expected (ie, I haven't attempted to validate OP's current code)

答案2

得分: 2

我建议查看BEGINFILE/ENDFILE,并牢记FNR(文件内的行数)和NR(全局行数)之间的区别,考虑以下示例。我有file1.txt的内容如下:

1
2
3

file2.txt的内容如下:

10
20
30
40

file3.txt的内容如下:

100
200
300
400
500

如果想要显示每个文件的总和和记录数,可以执行以下命令:

awk 'BEGINFILE{total=0}{total+=$1}ENDFILE{print FILENAME, "total value is", total, "number of records is", FNR}' file1.txt file2.txt file3.txt

得到输出:

file1.txt total value is 6 number of records is 3
file2.txt total value is 100 number of records is 4
file3.txt total value is 1500 number of records is 5

(在GNU Awk 5.1.0中测试通过)

英文:

> I want to repeat this command line at once but replace "A" in the file
> name with "D, G, K, M" etc. other than typing the line every time

I suggest taking look at BEGINFILE/ENDFILE and keeping in mind difference between FNR (number of row inside file) and NR (global number of row), consider following example, I have file1.txt with content

1
2
3

file2.txt with content

10
20
30
40

file3.txt with content

100
200
300
400
500

and want to show total and number of records in each file, then I could do

awk 'BEGINFILE{total=0}{total+=$1}ENDFILE{print FILENAME, "total value is", total, "number of records is", FNR}' file1.txt file2.txt file3.txt

getting output

file1.txt total value is 6 number of records is 3
file2.txt total value is 100 number of records is 4
file3.txt total value is 1500 number of records is 5

(tested in GNU Awk 5.1.0)

huangapple
  • 本文由 发表于 2023年7月17日 22:09:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76705288.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定