Использование даты 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
Здесь вы можете поиграть с разделителем записей 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'
Вы можете попробовать следующее:
awk -F' : ' '/^Product Name/{pn=$2}
/^Product Key/{pk=$2}
/^Computer Name/{print $2,pn,pk}' OFS=\; file
Разделитель полей FS
установлен на :
, чтобы получить значение поля с помощью $2
.
Разделитель полей вывода OFS
установлен на ;
.
Строка выводится каждый раз, когда встречается ключевое слово Computer Name
.
Правильный способ сделать это — создать массив, в котором хранится сопоставление имени тега со значением(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.