Сценарий, удаляющий лишние пробелы между буквами в тексте

Проблема маршрутизации была решена советом Celada отключить Reverse Path Filtering путем изменения файла /etc/sysctl. conf

net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0

Хотя теперь я понимаю, что для того, чтобы конкурировать с этой установкой, мне также нужно будет направлять возвращающиеся пакеты обратно через E и B, чтобы избежать фильтрации обратного пути моим провайдером.

12
12.09.2016, 01:00
10 ответов

Следующее регулярное выражение удалит первый пробел в любой строке пробелов. Это должно сработать.

s/ ( *)/\1/g

Примерно так:

perl -i -pe 's/ ( *)/\1/g' infile.txt

... заменит infile.txt на "фиксированную" версию.

16
27.01.2020, 19:54

Хотя это можно (и нужно) сделать с помощью однострочника 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
1
27.01.2020, 19:54

В 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;
    }

Изменил бы содержимое тестового текстового файла на ту же строку, но с удалением пробелов между буквами. (Для точности требуется пробел между каждой буквой).

0
27.01.2020, 19:54

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 возможных показаний в моей системе.

10
27.01.2020, 19:54
$ 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
0
27.01.2020, 19:54

Подобно версии Деви Моргана, но с sed:

$ echo "f o o  t h e  b a r" | sed -r "s/[ ]{1}([^ ]{1})/\1/g"
foo the bar
2
27.01.2020, 19:54

На основании того факта, что входные данные содержат двойные пробелы между словами, существует гораздо более простое решение. Вы просто заменяете двойные пробелы на неиспользуемый символ, удаляете пробелы и заменяете неиспользованный символ пробелом:

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:

Книга также имеет более важную аналитическую цель

13
27.01.2020, 19:54

Я пробовал это, и, похоже, это сработало:

echo "<text here>" | sed -r 's/(\w)(\s)/\1/g'

Команда sed захватывает две группы и возвращает только первую.

1
27.01.2020, 19:54

Примечание: этот ответ (как и некоторые другие здесь) основан на более ранней версии вопроса , в которой слова не были разделены. На более новую версию можно ответить тривиально .

Для таких входных данных, как:

Т е б о к а л с о х а с а н а н а н а л ю т и к а л п у р п о с е в х и х и с м о р е м п о р т а н т а н т

Вы можете попробовать:

 $ 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

Он обрабатывает слева направо и находит одно самое длинное слово после следующего.

Очевидно, что здесь это не лучший выбор слов, поскольку в этом предложении нет никакого смысла, но чтобы придумать правильное, вам потребуются инструменты, способные понять грамматику или значение текста или по крайней мере, некоторая статистическая информация о том, какие слова могут быть найдены вместе, чтобы дать наиболее вероятный набор слов. Похоже, решение - специализированная библиотека , найденная Линн

6
27.01.2020, 19:54

Используйте 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
18
27.01.2020, 19:54

Теги

Похожие вопросы