Проблема маршрутизации была решена советом Celada отключить Reverse Path Filtering путем изменения файла /etc/sysctl. conf
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0
Хотя теперь я понимаю, что для того, чтобы конкурировать с этой установкой, мне также нужно будет направлять возвращающиеся пакеты обратно через E и B, чтобы избежать фильтрации обратного пути моим провайдером.
Следующее регулярное выражение удалит первый пробел в любой строке пробелов. Это должно сработать.
s/ ( *)/\1/g
Примерно так:
perl -i -pe 's/ ( *)/\1/g' infile.txt
... заменит infile.txt на "фиксированную" версию.
Хотя это можно (и нужно) сделать с помощью однострочника Perl, небольшой синтаксический анализатор C тоже будет очень быстрым и очень маленьким (и, надеюсь, очень правильно):
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c1 = '\0', c2 = '\0', tmp_c;
c1 = fgetc(stdin);
for (;;) {
if (c1 == EOF) {
break;
}
c2 = fgetc(stdin);
if (c2 == EOF) {
if (c1 != ' ') {
fputc(c1, stdout);
}
break;
}
if (c1 == c2 && c1 == ' ') {
tmp_c = fgetc(stdin);
if (tmp_c != EOF) {
if (tmp_c != '\n') {
ungetc(tmp_c, stdin);
fputc(' ', stdout);
} else {
ungetc(tmp_c, stdin);
}
} else {
break;
}
} else if (c1 != ' ') {
fputc(c1, stdout);
}
c1 = c2;
}
exit(EXIT_SUCCESS);
}
Скомпилировано с помощью
gcc-4.9 -O3 -g3 -W -Wall -Wextra -std=c11 lilcparser.c -o lilcparser
(программа немного меньше 9 КБ)
Используется в конвейере, например:
echo "T h e b o o k a l s o h a s a n a n a l y t i c a l p u r p o s e w h i c h i s m o r e i m p o r t a n t " | ./lilcparser
В C ++ я бы сделал следующее:
#include <fstream>
using namespace std;
int main()
{
fstream is("test.txt", std::ios::in);
char buff;
vector<char>str;
while (!is.eof()){is.get(buff);str.push_back(buff);} //read file to string
for (int a=0;a<str.size();++a)if (str[a] == ' ' && str[a + 1] != ' ')str.erase(str.begin()+a);
is.close();
ofstream os("test.txt", std::ios::out | std::ios::trunc); //clear file for rewrite
os.write(str.data(), str.size() * sizeof(char)); //write chars
os.close();
return 0;
}
Изменил бы содержимое тестового текстового файла на ту же строку, но с удалением пробелов между буквами. (Для точности требуется пробел между каждой буквой).
Perl приходит на помощь!
Вам нужен словарь, то есть файл, в котором по одному слову в строке. В моей системе он существует как / var / lib / dict / words
, я также видел похожие файлы, как / usr / share / dict / british
и т. Д.
Сначала , вы помните все слова из словаря. Затем вы читаете введенные строки построчно и пытаетесь добавить символы к слову. Если есть возможность, запомните слово и попытайтесь проанализировать оставшуюся часть строки. Если вы дойдете до конца строки, вы выведете строку.
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my $words = '/var/lib/dict/words';
my %word;
sub analyze {
my ($chars, $words, $pos) = @_;
if ($pos == @$chars) {
$_[3] = 1; # Found.
say "@$words";
return
}
for my $to ($pos .. $#$chars) {
my $try = join q(), @$chars[ $pos .. $to ];
if (exists $word{$try}) {
analyze($chars, [ @$words, $try ], $to + 1, $_[3]);
}
}
}
open my $WORDS, '<', $words or die $!;
undef @word{ map { chomp; lc $_ } <$WORDS> };
while (<>) {
my @chars = map lc, /\S/g;
analyze(\@chars, [], 0, my $found = 0);
warn "Unknown: $_" unless $found;
}
На ваш выбор он генерирует 4092 возможных показаний в моей системе.
$ echo 'F o u r s c o r e a n d' | \
txr -t '(mapcar* (opip (split-str @1 " ")
(mapcar (op regsub #/ / ""))
(cat-str @1 " "))
(get-lines))'
Four score and
$ txr -e '(awk (:begin (set fs " "))
((mf (regsub #/ / ""))))' # mf: modify fields
F o u r s c o r e a n d
Four score and
$ awk -F' ' '{for(i=1;i<=NF;i++)gsub(/ /,"",$i);print}'
F o u r s c o r e a n d
Four score and
Подобно версии Деви Моргана, но с sed:
$ echo "f o o t h e b a r" | sed -r "s/[ ]{1}([^ ]{1})/\1/g"
foo the bar
На основании того факта, что входные данные содержат двойные пробелы между словами, существует гораздо более простое решение. Вы просто заменяете двойные пробелы на неиспользуемый символ, удаляете пробелы и заменяете неиспользованный символ пробелом:
echo "T h e b o o k a l s o h a s a n a n a l y t i c a l p u r p o s e w h i c h i s m o r e i m p o r t a n t " | sed 's/ /\-/g;s/ //g;s/\-/ /g'
... output:
Книга также имеет более важную аналитическую цель
Я пробовал это, и, похоже, это сработало:
echo "<text here>" | sed -r 's/(\w)(\s)/\1/g'
Команда sed
захватывает две группы и возвращает только первую.
Примечание: этот ответ (как и некоторые другие здесь) основан на более ранней версии вопроса , в которой слова не были разделены. На более новую версию можно ответить тривиально .
Для таких входных данных, как:
Т е б о к а л с о х а с а н а н а н а л ю т и к а л п у р п о с е в х и х и с м о р е м п о р т а н т а н т
Вы можете попробовать:
$ tr -d ' ' < file | grep -oiFf /usr/share/dict/words | paste -sd ' '
The book also has ana na l y tic al purpose which ism ore important
Он обрабатывает слева направо и находит одно самое длинное слово после следующего.
Очевидно, что здесь это не лучший выбор слов, поскольку в этом предложении нет никакого смысла, но чтобы придумать правильное, вам потребуются инструменты, способные понять грамматику или значение текста или по крайней мере, некоторая статистическая информация о том, какие слова могут быть найдены вместе, чтобы дать наиболее вероятный набор слов. Похоже, решение - специализированная библиотека , найденная Линн
Используйте wordsegment
, пакет НЛП для сегментации слов на чистом Python:
$ pip install wordsegment
$ python2.7 -m wordsegment <<<"T h e b o o k a l s o h a s a n a n a l y t i c a l p u r p o s e w h i c h i s m o r e i m p o r t a n t"
the book also has an analytical purpose which is more important