使用awk和Bash

时间:2017-03-18 19:51:55

标签: bash awk

我需要获取图书索引中出现的所有数字,并为其添加22。索引数据看起来像这样(例如):

Ubuntu, 120, 143, 154
Yggdrasil, 144, 170-171
Yood, Charles, 6
Young, Bob, 178-179
Zawinski, Jamie, 204

我正在尝试使用此脚本使用awk执行此操作:

#!/bin/bash

filename="index"
while read -r line
do
    echo $line | awk -v n=22 '{printf($1)}{printf(" " )}{for(i=2;i<=NF;i++)printf(i%2?$i+n:$i+n)", "};{print FS}'
done < "$filename"

接近工作但有以下问题:

  1. 它不适用于作为范围一部分的页码(例如,&#34; 170-171&#34;)而不是单个数字。
  2. 对于索引术语多于一个单词的条目(例如,&#34; X Windows&#34;和&#34; Young,Bob&#34;),输出仅显示术语中的第一个单词。第二个单词最终输出为数字22.(我知道为什么会发生这种情况 - 我的awk命令将$ 2视为一个数字,如果它是一个字符串,它假定它的值为0)但我可以& #39;弄清楚如何解决它。
  3. 披露:我绝不是一名awk专家。我正在寻找一种快速修改索引中页码的方法(这将在几天内完成),因为我的出版商决定在我准备好索引之后更改手稿中的分页。 awk对我来说似乎是最好的工具,但如果有人有更好的想法,我可以接受其他建议。基本上,我只需要一种方式来说&#34;取这个文件中的所有数字并添加22;不要改变任何其他事情。&#34;

4 个答案:

答案 0 :(得分:3)

例如:

perl -plE 's/\b(\d+)\b/$1+22/ge' index

输出

Ubuntu, 142, 165, 176
Yggdrasil, 166, 192-193
Yood, Charles, 28
Young, Bob, 200-201
Zawinski, Jamie, 226

但不是awk

答案 1 :(得分:3)

使用GNU awk进行多字符RS和RT:

$ awk -v RS='[0-9]+' '{ORS=(RT=="" ? "" : RT+22)}1' file
Ubuntu, 142, 165, 176
Yggdrasil, 166, 192-193
Yood, Charles, 28
Young, Bob, 200-201
Zawinski, Jamie, 226

答案 2 :(得分:1)

您可以使用此gnu awk命令:

awk 'BEGIN {FS="\f";RS="(, |-|\n)";} /^[0-9]+$/ {$1 = $1 +22} { printf("%s%s", $1, RT);}' yourfile
  • FSRS有一些滥用行为要让awk处理每行中的每个令牌自己的记录,所以你没有必要循环过来 字段并测试每个字段是否为数字
  • RS="(, |-|\n)"将破折号,换行符和“,”配置为记录分隔符
  • 在仅由数字组成的“记录”上:添加了22
  • printf打印令牌及其RT以重建文件中的行

答案 3 :(得分:0)

考虑使用以下awk脚本(add_number.awk):

BEGIN{ FS=OFS=", "; if (!n) n=22; }  # if `n` variable hasn't been passed the default is 22
{
    for (i=1;i<=NF;i++) {      # traversing fields
        if ($i~/^[0-9]+$/) {   # if a field contains a single number
            $i+=n;
        }  
        else if (match($i, /^([0-9]+)-([0-9]+)$/, arr)) {  # if a field contains `range of numbers`
            $i=arr[1]+n"-"arr[2]+n;
        } 
    }
    print;
}

用法:

awk -v n=22 -f add_number.awk testfile

输出:

Ubuntu, 142, 165, 176
Yggdrasil, 166, 192-193
Yood, Charles, 28
Young, Bob, 200-201
Zawinski, Jamie, 226