Я делаю сценарий оболочки для поиска биграмм, который вроде как работает.
#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 '\..'
Это отфильтрует любые строки, содержащие точку, которая не является последним символом строки.
Выражение grep соответствует (а опция -v исключает) всему, что соответствует точке, за которой следует то, что не является знаком доллара. Поскольку вывод tr не включает доллары, он работает, но не очевидно, что класс символов был необходим. Это могло быть просто "\ ..".
В сценариях оболочки можно использовать каналы.
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 читает новое слово. Когда old заканчивается точкой (как в начале), по вашим правилам он не образует действительную биграмму. Если вы хотите удалить точки из биграмм, заканчивающихся предложением, вы можете использовать:
echo "$old ${new%.}"
Версия без украшений (с отображенными точками) работает как с оболочкой Bourne, так и с ее производными; версия с ${new%.} работает только с оболочкой Korn и производными, а не с исходной оболочкой Bourne.
Если вам необходимо использовать временные файлы, укажите в их именах идентификатор процесса ($$) и удалите их с помощью ловушки:
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 for Poets" Кена Черча - классическое описание решений подобных проблем (pdf, оригинал)