Уважаемые коллеги!Я пишу скрипт, который должен перебрать все файлы из списка и разобрать с помощью 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.
>Уважаемые коллеги!
>
>Я пишу скрипт, который должен перебрать все файлы из списка и разобрать
>с помощью 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
Уважаемый allez, дело в том, что мне надо заполучить эту информацию в массиве. Запланирована обработка XML, в структуру которого будет вставлено разобранное по шаблону имя файла. Идея такая - разобрать имя файла в массив FNPart, шаблон вида "ID_Action_DD_MM_YY.xml" в массив Tags, потом создать такую строку: <Tag[1]><FNPart[1]></Tag[1]> ... <Tag[n]><FNPart[n]></Tag[n]> и вставить её в очередной XML (там запись в одну строку, поэтому можно вставить сгенерённую строчку между первыми найденными ><)
>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.
Соболезнования. Мужайтесь.
>>Почему строка утраивается?
>
>Потому что FILENAME - не только имя файла, но и... "три! четыре!!
>килограмма..." ...чтение его построчно. Утраивается -- потому, что три строки в
>соотв.файлах.
>Да, точно, в тех XML-файлах по три строки... В предыдущем ответе я описал задачу, которую надо решить, м.б., это можно сделать как-то проще?
>м.б., это можно сделать как-то проще?Можно, я не возражаю.
{printf FNParts[i] " | "}
-->
{print "<Tag["i"]>" FNParts[i] "</Tag["i"]>"}
или
{print "<"Tag[i]">"FNParts[i]"</"Tag[i]">"}
Ух ты, шикарно! Тогда ещё вопрос: шаблон имени файла задаётся переменной скрипта $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Но это падает с ошибкой синтаксиса.
>Ух ты, шикарно!Ну, да, мастерство не пропьёшь. 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
Интересно, можно ли как-нибудь ограничить набор входных строк и обрабатывать, например, только первую строку? Таким образом я смог бы убить все повторы, т.к., будет обрабатываться ровно одна строка. Я написал такое условие на входе: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, но оно не привело ни к чему хорошему - просто в случае выполнения шаблона выводится первая строка файла и все повторы из моего самого первого вопроса...
>Интересно, можно ли как-нибудь ограничить набор входных строк и обрабатывать, например, только
>первую строку?Решено использованием оператора {exit}.
Андрей, приветствую!А что означает
awk 'BEGIN{сделать_из_строки_массив_tag("'"$FileNameTemplate"'"}? Мне не удалось заставить скрипт заработать...
>[оверквотинг удален]
>Пока я догадался делать это вот так:
>
>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
После чего внутри скрипта все это обрабатывается. С содержанием скрипта не смогу помочь, так как задача изложена невразумительно (с моей точки зрения).
Приветствую!
Ниже распишу задачу более подробно. Надо слить несколько однотипных 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-скрипта не надо писать $ перед именем переменной. Задача успешно решена, всем участникам обсуждения большое спасибо!