【问题标题】:How do I get "awk" to modify only certain lines of a file, instead of the whole file?如何让“awk”只修改文件的某些行,而不是整个文件?
【发布时间】:2020-04-20 19:17:57
【问题描述】:

我想重用 this awk code,正确大写一些提示表音频文件。此代码不仅将所有单词大写,而且遵循一些大写规则,如链接问题中所述。

问题是如何修改此代码以大写只大写“TITLE”行,而不是整个文件。例如,使用这个简单的提示表:

FILE "Two The Beatles Songs.wav" WAVE
  TRACK 01 AUDIO
    TITLE "dig A pony"
    PERFORMER "The Beatles"
    INDEX 01 00:00:00
  TRACK 02 AUDIO
    TITLE "from me to you"
    PERFORMER "The Beatles"
    INDEX 01 03:58:02

还有一个简单的 for 循环加上 awk 代码,例如:

#!/bin/sh
for cue_file in *.cue
do
  awk 'BEGIN{split("a the to at in on with and but or",w); for(i in w)nocap[w[i]]}function cap(word){return toupper(substr(word,1,1)) tolower(substr(word,2))}{for(i=1;i<=NF;++i){printf "%s%s",(i==1||i==NF||!(tolower($i) in nocap)?cap($i):tolower($i)),(i==NF?"\n":" ")}}' "$cue_file" > ~/temp_cue_file && mv ~/temp_cue_file "$cue_file"
done

脚本运行后的结果一定是:

FILE "Two The Beatles Songs.wav" WAVE
  TRACK 01 AUDIO
    TITLE "Dig a Pony"
    PERFORMER "The Beatles"
    INDEX 01 00:00:00
  TRACK 02 AUDIO
    TITLE "From Me to You"
    PERFORMER "The Beatles"
    INDEX 01 03:58:02

TITLE "Dig a Pony" 而不是TITLE "dig A pony"。还有TITLE "From Me to You" 而不是TITLE "from me to you"

请求是:

  1. 如前所述,shell 脚本必须仅更改 TITLE 行(全部),而不能更改其余部分。
  2. shell 脚本必须在 POSIX sh shell 下运行。就我而言,FreeBSD。
  3. 如果有单行 awk 代码将不胜感激。
  4. 遵循相同的“大写规则”as the linked question(并遵循提供的 awk)。那就是:

    • 将所有单词大写,以下情况除外:
    • 小写所有冠词 (a, the)、介词 (to、at、in、with) 和并列连词 (and, but, or)
    • 无论词性如何,标题中的第一个和最后一个单词都大写

如何调整 awk 代码以获得此结果?

谢谢。


前一行 awk 代码,在链接的答案中显示为展开:

BEGIN { split("a the to at in on with and but or", w)
        for (i in w) nocap[w[i]] }

function cap(word) {
    return toupper(substr(word,1,1)) tolower(substr(word,2))
}

{
  for (i=1; i<=NF; ++i) {
      printf "%s%s", (i==1||i==NF||!(tolower($i) in nocap)?cap($i):tolower($i)),
                     (i==NF?"\n":" ")
  }
}

【问题讨论】:

  • 您是否努力理解最初发布的代码并尝试针对您的用例进行修改?
  • 是的,我做到了,但没有成功。我有 awk 的经验。

标签: awk


【解决方案1】:

请您尝试关注一下。

awk '
BEGIN{
  num=split("a the to at in on with and but or",array," ")
  for(i=1;i<=num;i++){
    smallLetters[array[i]]
  }
}
/TITLE/{
  for(i=2;i<=NF;i++){
    if(tolower($i) in smallLetters){
      $i=tolower(substr($i,1,1)) substr($i,2)
    }
    else{
      if($i~/^\"/){
        $i=substr($i,1,1) toupper(substr($i,2,1)) substr($i,3)
      }
      else{
        $i=toupper(substr($i,1,1)) substr($i,2)
      }
    }
  }
}
1
'  Input_file

说明:为上述代码添加详细说明。

awk '                                                                         ##Starting awk program from here.
BEGIN{                                                                        ##Starting BEGIN section of this program from here.
  num=split("a the to at in on with and but or",array," ")                    ##Creating array for all words needs to be of lower size.
  for(i=1;i<=num;i++){                                                        ##Running a for loop from i=1 to tillvalue of num(length of array).
    smallLetters[array[i]]                                                    ##Creating an array named smallLetters with index of variable i here.
  }
}
/TITLE/{                                                                      ##Checking condition if a line contains string TITLE then do following.
  for(i=2;i<=NF;i++){                                                         ##Running a for loop from 2nd field to last field of line.
    if(tolower($i) in smallLetters){                                          ##Checking condition if lower case current field is present in array smallLetters.
      $i=tolower(substr($i,1,1)) substr($i,2)                                 ##Changing current field to lower case for 1st letter and keeping rest same as it is.
    }
    else{                                                                     ##If current field is NOT in array then do following.
      if($i~/^\"/){                                                           ##Checking if field starts from " then do following.
        $i=substr($i,1,1) toupper(substr($i,2,1)) substr($i,3)                ##Only make 2nd letter Capital since 1st is "
      }
      else{
        $i=toupper(substr($i,1,1)) substr($i,2)                               ##Else make1st character capital and keep as it is.
      }
    }
  }
}
1                                                                             ##Printing edited/non-edited lines here.
'  Input_file                                                                 ##Mentioning Input_file name here.

【讨论】:

  • 哇!似乎它现在正在工作!请让我在接受之前再测试一下:)谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
相关资源
最近更新 更多