URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 8420
[ Назад ]

Исходное сообщение
"AWK SPLIT"

Отправлено SLario , 04-Сен-09 12:44 
Уважаемые коллеги!

Я пишу скрипт, который должен перебрать все файлы из списка и разобрать с помощью split имя каждого файла. Я делаю это так:

for file in `cat /$FileListFN`; do
     echo `awk   '
                 {N=split(FILENAME,FNParts,"_")}
                 {for (i=1; i<=N; i++)
                    {print FNParts[i] " | "}
                 }
                 ' $file`
done

При запуске я получаю что-то странное - из списка

BD52_New_28_04_09.xml
BD5A_New_28_04_09.xml
BD62_New_28_04_09.xml
BD6A_New_28_04_09.xml
BD72_New_28_04_09.xml
BD7A_New_28_04_09.xml
BD82_New_28_04_09.xml
BD8A_New_28_04_09.xml

получается такой вывод:

BD52 | New | 28 | 04 | 09.xml | BD52 | New | 28 | 04 | 09.xml | BD52 | New | 28 | 04 | 09.xml |
BD5A | New | 28 | 04 | 09.xml | BD5A | New | 28 | 04 | 09.xml | BD5A | New | 28 | 04 | 09.xml |
BD62 | New | 28 | 04 | 09.xml | BD62 | New | 28 | 04 | 09.xml | BD62 | New | 28 | 04 | 09.xml |
BD6A | New | 28 | 04 | 09.xml | BD6A | New | 28 | 04 | 09.xml | BD6A | New | 28 | 04 | 09.xml |
BD72 | New | 28 | 04 | 09.xml | BD72 | New | 28 | 04 | 09.xml | BD72 | New | 28 | 04 | 09.xml |
BD7A | New | 28 | 04 | 09.xml | BD7A | New | 28 | 04 | 09.xml | BD7A | New | 28 | 04 | 09.xml |
BD82 | New | 28 | 04 | 09.xml | BD82 | New | 28 | 04 | 09.xml | BD82 | New | 28 | 04 | 09.xml |
BD8A | New | 28 | 04 | 09.xml | BD8A | New | 28 | 04 | 09.xml | BD8A | New | 28 | 04 | 09.xml |

Почему строка утраивается? Мой скрипт аналогичен примерам, но там всё работает, как надо...

Система - Solaris.


Содержание

Сообщения в этом обсуждении
"AWK SPLIT"
Отправлено allez , 04-Сен-09 14:09 
>Уважаемые коллеги!
>
>Я пишу скрипт, который должен перебрать все файлы из списка и разобрать
>с помощью split имя каждого файла.

Использование split обязательно? Такой вариант не подойдет?

$ echo "BD8A_New_28_04_09.xml" | awk -F "_" '{for (i=1; i<=NF-1; i++) {printf $i " | "} print $NF}'
BD8A | New | 28 | 04 | 09.xml


"AWK SPLIT"
Отправлено SLario , 04-Сен-09 14:51 
Уважаемый allez, дело в том, что мне надо заполучить эту информацию в массиве. Запланирована обработка XML, в структуру которого будет вставлено разобранное по шаблону имя файла. Идея такая - разобрать имя файла в массив FNPart, шаблон вида "ID_Action_DD_MM_YY.xml" в массив Tags, потом создать такую строку: <Tag[1]><FNPart[1]></Tag[1]> ... <Tag[n]><FNPart[n]></Tag[n]> и вставить её в очередной XML (там запись в одну строку, поэтому можно вставить сгенерённую строчку между первыми найденными ><)

"AWK SPLIT"
Отправлено Andrey Mitrofanov , 04-Сен-09 14:57 
>for file in `cat /$FileListFN`; do
>     echo `awk   '
>     {N=split(FILENAME,FNParts,"_")}
>     {for (i=1; i<=N; i++)
>        {print FNParts[i] " | "}
>     }
>     ' $file`

$ echo "BD8A_New_28_04_09.xml" | gawk '{N=split($0,FNParts,"_"); for (i=1; i<=N; i++) {printf FNParts[i] " | "};print "";exit }'
BD8A | New | 28 | 04 | 09.xml |
$ gawk -v f="BD8A_New_28_04_09.xml" 'BEGIN{N=split(f,FNParts,"_"); for (i=1; i<=N; i++) {printf FNParts[i] " | "};print"";exit }'
BD8A | New | 28 | 04 | 09.xml |
$ echo "BD8A_New_28_04_09.xml" | sed 's/_/ | /g'
BD8A | New | 28 | 04 | 09.xml
$ _

>Почему строка утраивается?

Потому что FILENAME - не только имя файла, но и... "три! четыре!! килограмма..." ...чтение его построчно. Утраивается -- потому, что три строки в соотв.файлах.

>Система - Solaris.

Соболезнования. Мужайтесь.


"AWK SPLIT"
Отправлено SLario , 04-Сен-09 15:06 
>>Почему строка утраивается?
>
>Потому что FILENAME - не только имя файла, но и... "три! четыре!!
>килограмма..." ...чтение его построчно. Утраивается -- потому, что три строки в
>соотв.файлах.
>

Да, точно, в тех XML-файлах по три строки... В предыдущем ответе я описал задачу, которую надо решить, м.б., это можно сделать как-то проще?


"AWK SPLIT"
Отправлено Andrey Mitrofanov , 04-Сен-09 15:15 
>м.б., это можно сделать как-то проще?

Можно, я не возражаю.

{printf FNParts[i] " | "}
-->
{print "<Tag["i"]>" FNParts[i] "</Tag["i"]>"}
или
{print "<"Tag[i]">"FNParts[i]"</"Tag[i]">"}


"AWK SPLIT"
Отправлено SLario , 04-Сен-09 15:19 
Ух ты, шикарно! Тогда ещё вопрос: шаблон имени файла задаётся переменной скрипта $FileNameTemplate немного выше по тексту (не попало в мою копипасту). Массив должен быть сформирован из него. Можно ли запихнуть в AWK обработку переменной скрипта?

Пока я догадался делать это вот так:

FileNameTemplate="ID_Action_DD_MM_YY"

for file in `cat /$FileListFN`; do
   XMLInsertion=`echo $FileNameTemplate | awk '{N=split($0,Tags,"_")}{split(FILENAME,FNParts,"_")}{for (i=1; i<=N; i++) {print <Tags[i]><FNParts[i]><\Tags[i]>}}' $file`
   echo $XMLInsertion
done

Но это падает с ошибкой синтаксиса.


"AWK SPLIT"
Отправлено Andrey Mitrofanov , 04-Сен-09 16:14 
>Ух ты, шикарно!

Ну, да, мастерство не пропьёшь. B)

Тогда ещё вопрос: шаблон имени файла задаётся переменной скрипта
>$FileNameTemplate немного выше по тексту (не попало в мою копипасту). Массив
>должен быть сформирован из него. Можно ли запихнуть в AWK обработку
>переменной скрипта?

Ещё раз, внимательно:
""не только имя файла, но и... "три! четыре!! килограмма..." ...чтение его построчно""

=Почитай, чего awk делает с входным файлом (бишь stdin-ом). Это в "man awk", где-то там. Или man nawk, или man mawk, или man gawk... В любом из них. Главное найти - два абзаца примерно.

>
>Пока я догадался делать это вот так:
>FileNameTemplate="ID_Action_DD_MM_YY"
>
>for file in `cat /$FileListFN`; do
>   XMLInsertion=`
>Но это падает с ошибкой синтаксиса.

С кавычками (экранированием спец.символов) всё _очень_ плохо.

Пятница... Семья не ждёт?..

FileNameTemplate="ID_Action_DD_MM_YY"

cat /$FileListFN \
awk 'BEGIN{сделать_из_строки_массив_tag("'"$FileNameTemplate"'"}
'{N=split($0,FNParts,"_")
printf $0" "
for (i=1; i<=N; i++) {
printf "<"Tag[i]">"FNParts[i]"</"Tag[i]">"
};print"";exit }' |\
while read filename xfragment; do
  # работать с $filename + $xfragment ...
done


"AWK SPLIT"
Отправлено SLario , 07-Сен-09 10:12 
Интересно, можно ли как-нибудь ограничить набор входных строк и обрабатывать, например, только первую строку? Таким образом я смог бы убить все повторы, т.к., будет обрабатываться ровно одна строка. Я написал такое условие на входе:

for file in `cat /$FileListFN`; do
   echo `awk  'NR==1
               {N=split(FILENAME,FNParts,"_")}
               {for (i=1; i<=N; i++)
                  {print FNParts[i]}
               }' $file`
   echo $XMLInsertion
done

, но оно не привело ни к чему хорошему - просто в случае выполнения шаблона выводится первая строка файла и все повторы из моего самого первого вопроса...


"AWK SPLIT"
Отправлено SLario , 09-Сен-09 15:30 
>Интересно, можно ли как-нибудь ограничить набор входных строк и обрабатывать, например, только
>первую строку?

Решено использованием оператора {exit}.


"AWK SPLIT"
Отправлено SLario , 07-Сен-09 12:21 
Андрей, приветствую!

А что означает
awk 'BEGIN{сделать_из_строки_массив_tag("'"$FileNameTemplate"'"}? Мне не удалось заставить скрипт заработать...


"AWK SPLIT"
Отправлено mx3ix , 04-Сен-09 16:22 
>[оверквотинг удален]
>Пока я догадался делать это вот так:
>
>FileNameTemplate="ID_Action_DD_MM_YY"
>
>for file in `cat /$FileListFN`; do
>   XMLInsertion=`echo $FileNameTemplate | awk '{N=split($0,Tags,"_")}{split(FILENAME,FNParts,"_")}{for (i=1; i<=N; i++) {print <Tags[i]><FNParts[i]><\Tags[i]>}}' $file`
>   echo $XMLInsertion
>done
>
>Но это падает с ошибкой синтаксиса.

Вопрос не понятен. Очень сложный слог изложения. Не прослеживается формализация задачи. Но, все-таки, попробую помочь.

Передача параметров в AWK (это написано в MAN и неоднократно проверено на практике) осуществляется посредством -v параметра. Например:

awk -f MyMegaSuperAWKScript.awk -v FileNameTemplate=$MYMEGASUPERSHELLVARIABLE

После чего внутри скрипта все это обрабатывается. С содержанием скрипта не смогу помочь, так как задача изложена невразумительно (с моей точки зрения).


"AWK SPLIT"
Отправлено SLario , 07-Сен-09 12:11 
Приветствую!
Ниже распишу задачу более подробно. Надо слить несколько однотипных XML-файлов в один большой XML, не потеряв при этом информацию об исходных файлах. Сохранять информацию предлагается в дополнительных тегах, которые добавятся в основной текст. Исходные XML-файлы представляют собой длинные строки, т.е., в первой строке лежит заголовок XML, а в следующих - записи XML, по одной записи на строку. Идея такая - шаблон имени файла (из входного параметра) разобрать в один массив Tag, имя текущего файла разобрать в другой массив FNPart, потом склеить из них XML-подобную строку вида
<Tag[1]><FNPart[1]></Tag[1]> ... <Tag[n]><FNPart[n]></Tag[n]>,
после этого выкинуть из очередного файла строку №1 (с заголовком) и работать только с остальными, заменяя в них самое первое вхождение сочетания >< на ><Tag[1]><FNPart[1]></Tag[1]> ... <Tag[n]><FNPart[n]></Tag[n]><. Этим я добьюсь добавления в текуший файл XML информации о названии этого файла. А потом я возьму шаблон заголовка (заголовок XML + открывающий общий тег), прилью к нему полученные строки из разных файлов XML с внедрённой информацией и закрою файл шаблоном подвала XML (закрывающий общий тег). Таким образом получается, что надо два раза использовать split, затем выводить результат склеивания в переменную shell, затем sed будет менять (начиная со второй строки) первое вхождение >< и менять его на >переменная<. Пока я завис на этапе ввода в awk переменной скрипта, хранящей шаблон имени файла. Подключенная внешняя переменная не видится в программе awk:

for file in `cat /$FileListFN`; do
   echo `awk  '{print $FNT}
               {N=split($FNT,Tags,"_")}
               {for (i=1; i<=N; i++)
                 {print Tags[i] " | "}
               }    
               {exit}
               ' $file -v FNT=$FileNameTemplate`
done

{exit} нужен для того, чтобы обрабатывать всё только один раз. Этот скрипт почему-то ничего не выводит, ждёт ввода с клавиатуры...


"AWK SPLIT"
Отправлено SLario , 09-Сен-09 15:32 
Выяснил, что внутри awk-скрипта не надо писать $ перед именем переменной. Задача успешно решена, всем участникам обсуждения большое спасибо!