Shell скрипт для поиска биграмм
Вопрос
Я делаю сценарий оболочки для поиска биграмм, который работает, вроде того.
#tokenise words
tr -sc 'a-zA-z0-9.' '\012' < $1 > out1
#create 2nd list offset by 1 word
tail -n+2 out1 > out2
#paste list together
paste out1 out2
#clean up
rm out1 out2
Единственная проблема заключается в том, что он объединяет слова в конце и начале предыдущего предложения.
Например, для двух предложений «Привет, мир». и 'Foo Bar.' я получу связь с миром. Foo». Можно ли отфильтровать их с помощью grep или чего-то еще?
Я знаю, что могу найти все биграммы, содержащие полную остановку с помощью grep [.], но это также находит законные биграммы.
Решение
Просто замените строку вставки следующим образом:
paste out1 out2 | grep -v '\..'
Это отфильтрует все строки, содержащие точку, которая не является последним символом строки.
Другие советы
Сценарии оболочки могут использовать каналы.
cat "$@" |
tr -cs "a-zA-Z0-9." '\012' |
{
old="aaa."
while read new
do
case "$old" in
*.) : OK;;
*) echo "$old $new";;
esac
old="$new"
done
}
Код использует cat
в качестве универсального сборщика данных - tr
- это чистый фильтр, который не принимает никаких аргументов имени файла. Основная идея заключается в том, что переменная old содержит первое слово, а new читает новое слово. Когда старое заканчивается точкой (как это происходит в начале), оно не формирует действительный биграмм по вашим правилам. Если вы хотите удалить точки из биграмм с окончанием предложения, вы можете использовать:
echo "$old ${new%.}"
Неукрашенная версия (с отображаемыми точками) работает как с оболочкой Bourne, так и с производными; версия с $ {new%.}
только работниками с оболочкой Korn и производными - не оригинальной оболочкой Bourne.
Если вам необходимо использовать временные файлы, сделайте так, чтобы их имена содержали идентификатор процесса ($$) и используйте trap для их удаления:
tmp=${TMPDIR:-/tmp}/bigram.$
trap 'rm -f $tmp.?; exit 1' 0 1 2 3 13 15
...code using $tmp.1, $tmp.2, etc...
rm -f $tmp.?
trap 0
Сигнал 1 - это зависание (HUP), 2 - это прерывание (INT), 3 - это выход (QUIT), 13 - канал (PIPE) и 15 - завершение (TERM); 0 - это «любой выход», и в этом контексте это почти что юджу. Перед фактическим выходом не забудьте отменить выходную ловушку, как показано.
Вы также можете просмотреть Unix для поэтов Кена Черча " (PDF) - классическое описание решений подобных проблем.