Измените некоторый awk-код, чтобы он соответствовал предыдущим пробелам в измененной строке - PullRequest
0 голосов
/ 21 апреля 2020

Учитывая код awk из этого принятого ответа :

awk '
BEGIN{
  s1="\""
  num=split("McCartney feat. vs. CD USA NYC",array," ")
  for(k=1;k<=num;k++){
     temp=tolower(array[k])
     ignoreLetters[temp]=array[k]
  }
  num=split("a the to at in on with and but or",array," ")
  for(i=1;i<=num;i++){
    smallLetters[array[i]]=array[i]
  }
}
/TITLE/{
  for(i=2;i<=NF;i++){
    front=end=nothing=both=""
    if($i~/^"/ && $i!~/"$/){
      temp=tolower(substr($i,2))
      front=1
    }
    else if($i ~ /^".*"$/){
      temp=tolower(substr($i,2,length($i)-2))
      both=1
    }
    else if($i ~/"$/ && $i!~/^"/){
      temp=tolower(substr($i,1,length($i)-1))
      end=1
    }
    else{
      temp=tolower($i)
      nothing=1
    }
    if(temp in ignoreLetters){
      if(front){
         $i=s1 ignoreLetters[temp]
      }
      else if(end){
         $i=ignoreLetters[temp] s1
      }
      else if(both){
         $i=s1 ignoreLetters[temp] s1
      }
      else if(nothing){
         $i=ignoreLetters[temp]
      }
    }
    else if(temp in smallLetters){
      if(front){
         $i=s1 smallLetters[temp]
      }
      else if(end){
         $i=smallLetters[temp] s1
      }
      else if(nothing){
         $i=smallLetters[temp]
      }
      else if(both){
         $i=s1 smallLetters[temp] s1
      }
    }
    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

Этот код правильно вводит строки, которые содержат TITLE в Input_file, после четырех основных c правила:

  1. Используйте все слова с заглавными буквами.
  2. Строчные символы для данного массива: "a the to at in on with and but or".
  3. Соблюдайте указанную заглавную букву второго массива: "McCartney feat. vs. CD USA NYC".
  4. Использование заглавных букв в первом и последнем слове в заголовке с учетом массива прописных букв в пункте 3.

Проблема заключается в том, что код awk сокращает пробелы перед строками TITLE.

Например, учитывая это Input_file:

FILE "Two The Beatles Songs.wav" WAVE
  TRACK 01 AUDIO
    TITLE "dig A pony, Feat. paul mccartney"
    PERFORMER "The Beatles"
    INDEX 01 00:00:00
  TRACK 02 AUDIO
    TITLE "From Me to You"
    PERFORMER "The Beatles"
    INDEX 01 03:58:02

Это делает:

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

И мне нужно это:

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

В этом Input_file число пробелов, предшествующих TITLE, равно четырем, но это не всегда! Код awk должен:

  • Учитывать количество пробелов, предшествующих TITLE.
  • Кроме того, соблюдайте любое количество TAB (\ t), предшествующих TITLE, обычно это TAB. вместо пробелов!

Спасибо.

1 Ответ

1 голос
/ 21 апреля 2020

Не могли бы вы попробовать следующее. Добавлена ​​функция match для получения начальных / начальных пробелов и сохранения их в переменной; затем снова добавляем его до $1, так как после редактирования полей начальные пробелы будут потеряны, поэтому их повторное добавление даст нам начальные пробелы.

awk '
BEGIN{
  s1="\""
  num=split("McCartney feat. vs. CD USA NYC",array," ")
  for(k=1;k<=num;k++){
     temp=tolower(array[k])
     ignoreLetters[temp]=array[k]
  }
  num=split("a the to at in on with and but or",array," ")
  for(i=1;i<=num;i++){
    smallLetters[array[i]]=array[i]
  }
}
/TITLE/{
  match($0,/^[[:space:]]+/)
  spaces=substr($0,RSTART,RLENGTH)
  for(i=2;i<=NF;i++){
    front=end=nothing=both=""
    if($i~/^"/ && $i!~/"$/){
      temp=tolower(substr($i,2))
      front=1
    }
    else if($i ~ /^".*"$/){
      temp=tolower(substr($i,2,length($i)-2))
      both=1
    }
    else if($i ~/"$/ && $i!~/^"/){
      temp=tolower(substr($i,1,length($i)-1))
      end=1
    }
    else{
      temp=tolower($i)
      nothing=1
    }
    if(temp in ignoreLetters){
      if(front){
         $i=s1 ignoreLetters[temp]
      }
      else if(end){
         $i=ignoreLetters[temp] s1
      }
      else if(both){
         $i=s1 ignoreLetters[temp] s1
      }
      else if(nothing){
         $i=ignoreLetters[temp]
      }
    }
    else if(temp in smallLetters){
      if(front){
         $i=s1 smallLetters[temp]
      }
      else if(end){
         $i=smallLetters[temp] s1
      }
      else if(nothing){
         $i=smallLetters[temp]
      }
      else if(both){
         $i=s1 smallLetters[temp] s1
      }
    }
    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=spaces $1
}
1
'  Input_file

Логическое понимание ответа:

  • В разделе BEGIN, в котором упоминаются все слова в виде массива, один массив равен ignoreLetters, в котором будут игнорироваться слова, и они не будут применяться, делая их маленькими буквами или делая их 1-я буква заглавная. smallLetters будет содержать слова, содержащие все те слова, которые должны быть строчными буквами.
  • Затем ищем строку с TITLE.
  • Сначала ищем начальные пробелы и сохраняем их в переменную.
  • Затем проходит по всем полям текущей строки.
  • Теперь проверяем 3 условия, если у поля есть " начало поля ИЛИ или конец поля или начало И конец обоих для поля.
  • Затем, в соответствии с вышеприведенным условием, проверяет, к какому массиву он приходит, если входит в ignoreLetters, затем сохраняет свое значение в соответствии с заданными значениями OP. Если оно входит в smallLetters, тогда сохраняйте значения маленькими буквами. Если значение текущего поля не встречается ни в одном из этих 2, сделайте его первую букву заглавной (проверяя " 3 случая, как упоминалось ранее).
  • Сохранение нового значения в значение поля и, наконец, добавление пробелов в $1 перед печатью. Затем печатать текущую строку.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...