awk - проблема с printf

Использование даты GNU и грубой силы:

start=20170101
end=20170630
cur=$start

increment="1 day"
while [ $(date +%s -d "$cur") -le $(date +%s -d "$end") ]
do
  if [ "$(date +%A -d "$cur")" = "Saturday" ]
  then
    printf "%s\n" "$cur"
    increment="1 week"
  fi
  cur=$(date +%Y%m%d -d "$cur + $increment")
done
1
21.08.2019, 05:21
3 ответа

Здесь вы можете поиграть с разделителем записей awk (RS). Установка его на ==================================================или ={50}, что является тем же самым, но в качестве регулярного выражения, позволяет вам рассматривать каждый набор значений, связанных с одним продуктом, как одну «строку». Если вы затем установите разделитель полей вывода(OFS)на ;и разделитель полей ввода(FSили параметр -F)на\n(новую строку )или :, это позволит вам сделать подобные маленькие хитрости (с использованием GNU awk):

$ awk RS='={50}' \
      -v OFS=';' \
      -F'[\n:]' \
      'NR%2==0{print $16,$3,$7}' file 
 PC-000-0; Microsoft Office Professional 2013; 00000-00000-00000-00000-00000
 PC-000-0; Windows 10 Pro; 00000-00000-00000-00000-00000

Поскольку каждая запись имеет=============================================(50=)выше и одну внизу, мы хотим прочитать только каждую вторую «строку». Вот что делает проверка NR%2==0.

Там есть несколько дополнительных пробелов, один в начале каждой строки и один между полями. Если они проблема,вы можете удалить их с помощьюsed:

$ awk -v RS='={50}' \
      -v OFS=';' \
      -F '[\n:]' \
      'NR%2==0{print $16,$3,$7}' file | 
        sed -e 's/^ //' -e 's/; /;/g'
PC-000-0;Microsoft Office Professional 2013;00000-00000-00000-00000-00000
PC-000-0;Windows 10 Pro;00000-00000-00000-00000-00000

Использование регулярного выражения для RSявляется расширением GNU, поэтому, вероятно, не будет работать на вашей macOS. Если нет, попробуйте это:

$ awk -v RS='=' \
      -v OFS=';' \
      -F'[\n:]' \
     'NR%50==1 && $2{print $16,$3,$7}' file |
        sed -e 's/^ //' -e 's/; /;/g'
1
27.01.2020, 23:30

Вы можете попробовать следующее:

awk -F' : ' '/^Product Name/{pn=$2}
             /^Product Key/{pk=$2}
             /^Computer Name/{print $2,pn,pk}' OFS=\; file

Разделитель полей FSустановлен на :, чтобы получить значение поля с помощью $2.

Разделитель полей вывода OFSустановлен на ;.

Строка выводится каждый раз, когда встречается ключевое слово Computer Name.

1
27.01.2020, 23:30

Правильный способ сделать это — создать массив, в котором хранится сопоставление имени тега со значением(f[]ниже ), а затем просто печатать нужные значения в конце каждой записи, например.:

$ cat tst.awk
BEGIN { OFS=";" }
{
    sub(/\r$/,"")
    tag = val = $0
    sub(/[[:space:]]*:.*/,"",tag)
    sub(/[^:]+[[:space:]]*:[[:space:]]*/,"",val)
    f[tag] = val
}
/^=/ && (cnt++)%2 {
    print f["Computer Name"], f["Product Name"], f["Product Key"]
    delete f
}

$ awk -f tst.awk file
PC-000-0;Microsoft Office Professional 2013;00000-00000-00000-00000-00000
PC-000-0;Windows 10 Pro;00000-00000-00000-00000-00000

При таком же подходе можно легко преобразовать весь входной файл в CSV, если хотите.:

$ cat tst.awk
BEGIN { OFS=";" }
!/^=/ {
    sub(/\r$/,"")
    tag = val = $0
    sub(/[[:space:]]*:.*/,"",tag)
    sub(/[^:]+[[:space:]]*:[[:space:]]*/,"",val)
    if ( !seen[tag]++ ) {
        tags[++numTags] = tag
    }
    f[tag] = val
}
/^=/ && (cnt++)%2 {
    if ( !doneHdr++ ) {
        for (tagNr=1; tagNr<=numTags; tagNr++) {
            tag = tags[tagNr]
            printf "\"%s\"%s", tag, (tagNr<numTags ? OFS : ORS)
        }
    }

    for (tagNr=1; tagNr<=numTags; tagNr++) {
        tag = tags[tagNr]
        printf "\"%s\"%s", f[tag], (tagNr<numTags ? OFS : ORS)
    }

    delete f
}

$ awk -f tst.awk file
"Product Name";"Product ID";"Product Key";"Installation Folder";"Service Pack";"Build Number";"Computer Name";"Modified Time"
"Microsoft Office Professional 2013";"00000-00000-00000-00000";"00000-00000-00000-00000-00000";"C:\Program Files\Microsoft Office\Office15\";"";"";"PC-000-0";"06.12.2018 14:03:44"
"Windows 10 Pro";"00000-00000-00000-00000";"00000-00000-00000-00000-00000";"C:\Windows";"";"17763";"PC-000-0";"18.07.2019 09:50:37";""

Измените OFS=";"на OFS=",", и на выходе будет файл, который можно дважды -щелкнуть в Windows, чтобы он правильно отображался в Excel.

0
27.01.2020, 23:30

Теги

Похожие вопросы