在awk中替换一个字符

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

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:

  1. 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 脚本将处理所有文件作为一个大数据集)。

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

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

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

  1. function print_output() {
  2. if (rowcnt > 0)
  3. print FILENAME, avg, sqrt(642)*sqrt(mean2 / rowcnt)
  4. delta = avg = mean2 = ""
  5. rowcnt = 0
  6. }
  7. FNR==1 { print_output() }
  8. { rowcnt++
  9. delta = $1 - avg
  10. avg += delta / rowcnt
  11. mean2 += delta * ($1 - avg)
  12. }
  13. END { print_output() }

注意:

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

You can try:

  1. 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:

  1. for fname in param_[ADGKM]_ratio_re_truncated.txt
  2. do
  3. echo "######### input: ${fname}"
  4. awk '.....' "${fname}"
  5. 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:

  1. awk '
  2. function print_output() {
  3. if (rowcnt > 0)
  4. print FILENAME, avg, sqrt(642)*sqrt(mean2 / rowcnt)
  5. delta = avg = mean2 = "" # reset variables for next file
  6. rowcnt = 0
  7. }
  8. FNR==1 { print_output() } # FNR==1 => new file so print results for previous file
  9. { rowcnt++
  10. delta = $1 - avg
  11. avg += delta / rowcnt
  12. mean2 += delta * ($1 - avg)
  13. }
  14. END { print_output() } # print results for last file
  15. ' 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. 1
  2. 2
  3. 3

file2.txt的内容如下:

  1. 10
  2. 20
  3. 30
  4. 40

file3.txt的内容如下:

  1. 100
  2. 200
  3. 300
  4. 400
  5. 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

得到输出:

  1. file1.txt total value is 6 number of records is 3
  2. file2.txt total value is 100 number of records is 4
  3. 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. 1
  2. 2
  3. 3

file2.txt with content

  1. 10
  2. 20
  3. 30
  4. 40

file3.txt with content

  1. 100
  2. 200
  3. 300
  4. 400
  5. 500

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

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

  1. file1.txt total value is 6 number of records is 3
  2. file2.txt total value is 100 number of records is 4
  3. 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:

确定