Хотя это может показаться простым вначале, сделать это правильно и обработать начальный тест для существующих файлов, усечение, если файл существует, а также обрабатывать повторяющиеся записи в имени файла в разных частях входного файла - занимает немного работы.
Вам необходимо отследить имена файлов, которые были созданы до сих пор по сценарию, и если тот же файл снова отображается, вам необходимо продолжить добавление к файлу вместо обрезания и начать новый файл.
После того как вы определили логику, фактический сценарий не слишком сложный. В то время как есть, вероятно, много других способов сделать это, вот один из способов, чтобы удовлетворить ваши требования:
Добавление строк из нескольких файлов
#!/bin/bash
tfn='sqlfname.tmp' ## tmp file to track filenames created across multiple files
while read -r line; do
if [ $(expr "$line" : "^use[ ].*$") -gt 0 ]; then ## begins with 'use'
fname=$(expr "$line" : "^use[ ]\(.*\)[;]$") ## filename after 'use'
if [ ! -f "$tfn" ]; then ## if tmp file does not exist create
:> "$fname"
echo " creating $fname"
echo "$fname" >> "$tfn"
continue
fi
if ! grep -q "$fname" "$tfn" ; then ## check if filename in tmp file
:> "$fname"
echo " creating $fname"
echo "$fname" >> "$tfn"
fi
continue
fi
echo " $line --> $fname" ## output to terminal (debug info)
echo "$line" >> "$fname" ## output to "$fname"
done < "$1"
exit 0
Супер простая версия ж/Нет Revision Control
Кроме того, если вам не нужно отслеживать, какие файлы были созданы, и вы будете будет ответственным за удаление/сброс файлов TestX
, если это необходимо, затем вы можете использовать очень упрощенную версию.
Единственный недостаток здесь заключается в том, что все файлы TestX
не могут начаться в определенный момент времени. Это может быть совершенно нормально для вас, но причина для отслеживания файлов в первую очередь заключалась в том, чтобы гарантировать известную отправную точку для содержимого в каждом файле.
С точки зрения сценария, по крайней мере без гарантии того, что последовательной точки во времени, ответственность ложится на пользователя (вы), чтобы удалить все файлы TestX
перед началом окончательного разбора всех SQL-файлов для их создания. Но..он делает сценарий очень простой :)
#!/bin/bash
while read -r line; do
if [ $(expr "$line" : "^use[ ].*$") -gt 0 ]; then ## begins with 'use'
fname=$(expr "$line" : "^use[ ]\(.*\)[;]$") ## filename after 'use'
continue
fi
echo " $line --> $fname" ## output to terminal (debug info)
echo "$line" >> "$fname" ## output to "$fname"
done < "$1"
exit 0
Входной
$ cat dat/sqlcreate.txt
use Test1;
aaaa
bbb
ccc
use Test2;
zzzz
dddd
use Test3;
jjj
use Test1;
kkk
lll
Выход
$ bash parsecreatesql.sh dat/sqlcreate.txt
creating Test1
aaaa --> Test1
bbb --> Test1
ccc --> Test1
creating Test2
zzzz --> Test2
dddd --> Test2
creating Test3
jjj --> Test3
kkk --> Test1
lll --> Test1
Файлы Создано/Content
$ printf "\nTest1\n"; cat Test1; printf "\nTest2\n"; \
cat Test2; printf "\nTest3\n"; cat Test3
Test1
aaaa
bbb
ccc
kkk
lll
Test2
zzzz
dddd
Test3
jjj
Сообщите мне, если у вас есть вопросы. Исходная версия перемещается ниже, если вам все равно придется рисовать.
Добавление строк из одного файла (оригинальное)
#!/bin/bash
declare -a created ## array to track filenames created
while read -r line; do
# if [ "${line%% *}" = "use" ]; then ## test begins with 'use'
if [ $(expr "$line" : "^use[ ].*$") -gt 0 ]; then
# fname=${line##* }
# fname=${fname%;} ## parse filename after 'use'
fname=$(expr "$line" : "^use[ ]\(.*\)[;]$")
entries=${#created[@]} ## check number files created
if [ "$entries" -eq 0 ]; then ## if 0, truncate add to array
:> "$fname"
echo " creating $fname"
created+=("$fname")
continue
else ## check all filenames in array
for ((i = 0; i < entries; i++)) do
[ "${created[i]}" = "$fname" ] && break ## already created, skip
if [ "$i" -eq $((entries - 1)) ]; then ## if not, create
:> "$fname"
echo " creating $fname"
created+=("$fname")
fi
done
continue
fi
fi
echo " $line --> $fname" ## output to terminal (debug info)
echo "$line" >> "$fname" ## output to "$fname"
done < "$1"
exit 0
Благодарности это работает как шарм, но одна проблема с этим .. этот сценарий будет Grep для любого «использовать» строки во всех line У меня есть небольшое условие, которое мы должны добавить здесь. if ["$ {line %% *}" = "use"]; то можем ли мы что-то изменить, если ["$ {line %% *}" = "^ use"]; затем используя эту крышку «^ используйте» только grep для линии, начинающейся с использования. Таким образом, код wiil не сломается, можете ли вы помочь на том же – sai
Итак, вы хотите привязать 'use' к началу строки. Вы можете изменить тип теста на 'if [$ (expr" $ line ":"^use []. * $ ") -Gt 0]' Я обновлю скрипт. –
Я также заменил встроенные выражения для синтаксического анализа 'fname' с помощью регулярного выражения' fname = $ (expr "$ line": "^ use [] \ (. * \) [;] $") ', Что эквивалентно. Единственный недостаток 'expr' - это немного медленнее, чем встроенные, но для небольших заданий (менее 100 000 строк это не так уж плохо). Я оставил оригинальные встроенные комментарии. Выбирайте. Если вы имеете дело с именами файлов, которые потенциально имеют пробелы, вы должны удвоить котировку всей подстановки команды (например, 'fname =" $ (expr ...) "' –