LINUX.ORG.RU

манипуляции с текстом ч.2


0

2

есть строка типа

aasffdjhdghneeraasdaeaashndasghs


может состоять из совершенно любых символов любых кодировок
нужно убрать все повторяющиеся символы т.е привести к виду:

asfdjhgner


В чем проблема? Банальное если (i+1)-ый символ равен i-ому символу удалить (i+1)-ый символ

abs ★★★
()
Ответ на: комментарий от serles

Я просто алгоритм сказал, не для баша.

abs ★★★
()
Ответ на: комментарий от anonymous

не годится:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe8 in position 1: invalid continuation byte

serles
() автор топика
Ответ на: комментарий от qulinxao

чего-то не то:

echo «aasffdjhdghneeraasdaeaashndasghs» |sed «s/./&\n/g» |uniq |sed -z «s/\n//g» |xargs echo


выхлоп - asfdjhdghnerasdaeashndasghs
Нужно убрать не подряд идущие дубли, а все

serles
() автор топика
Ответ на: комментарий от serles
  • скармливаешь циклу по одному символу (например как выше)
  • в цикле читаешь переменную
  • проверяешь, стоит ли единичка в ассоциативном массиве с индексом переменной
  • если не стоит:
    • ставишь единичку
    • пишешь на выход считанную переменную
ziemin ★★
()
Ответ на: комментарий от batekman

не получается:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbb in position 1845: invalid start byte

serles
() автор топика

может состоять из совершенно любых символов любых кодировок

Если строка состоит из символов «любых кодировок», то это не строка, а последовательность бит непонятного смысла, и в ней нельзя проводить операции над символами, пока не определишь кодировки.

proud_anon ★★★★★
()
Ответ на: комментарий от serles

Выше же тебе писали cat file.txt |.... Принцип тот же: убираешь echo и ставишь cat.

Только если у тебя там какой-то дикий двоичный файл скрипт может и не сработать. Что у тебя за данные и почему там все кодировки? Может и семибитная есть?

ziemin ★★
()
#! /usr/bin/perl

use 5.010;
use strict;
use warnings;
use utf8;
use open qw(:std :utf8);

my $string = <STDIN>;
chomp $string;
my @letters = split //, $string;

my @output;
my %seen;

for my $letter (@letters) {
    if (!defined $seen{$letter}) {
	$seen{$letter}++;
	push @output, $letter;
    } 
}

say @output;
$echo 'Ололо трололо!11расрас ©®™'  |./duplicates.pl 
Оло тр!1ас©®™
$
Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)

dron@gnu:~$ cat del.c 
#include <stdio.h>

int main(int argc, char *argv[])
{
    char  str[]="aasffdjhdghneeraasdaeaashndasghs";
    int buff;

    for (int i = 0; str[i] != '\0'; )
    {
        buff=str[i];
        i++;
        for(int x=i; str[x]!='\0';x++)
        {
            if(buff == str[x])
            str[x]=EOF;
        }
    }

    for (int z = 0;str[z] != '\0' ; z++)
    {
        if(str[z] != EOF)
        printf("%c",str[z]);
    }

    printf("\n");

    return 0;
}
dron@gnu:~$ gcc -std=c99 del.c ; ./a.out 
asfdjhgner
dron@gnu:~$ 


Dron ★★★★★
()
Ответ на: комментарий от ziemin

в файле 16777216 строк комбинации цифр 1-8, в каждой строке по 8 знаков Выхлоп -12345678 А как записать в файл?

serles
() автор топика
Ответ на: комментарий от serles

Файл поделен на строки? Надо, чтобы символы были уникальны в пределах строки или всего файла?

Nervous ★★★★★
()
Ответ на: комментарий от serles

Уже чувствую надо весь код приводить:

cat file.txt | sed "s/./&\n/g" | (
  while read c
  do
    if [ "${in[x$c]}" != "1" ]
    then
      in[x$c]=1
      echo -n $c
    fi
  done
) > file2.txt

Выходной файл file2.txt

комбинации цифр 1-8
Выхлоп -12345678

Это и есть твои кодировки?

ziemin ★★
()
Ответ на: комментарий от serles
dron@gnu:~$ cat del.c 
#include <stdio.h>
#include <assert.h>
#define MAXLEN 100500 /*Новые угарные серии на KарамбаTV ::)*/
int main(void)
{
    const char my_file[]="/home/dron/test.txt";
    int buff;
    char str[MAXLEN];

    FILE * stream=fopen(my_file,"r");
    assert(stream);

    for (int i = 0; (buff=fgetc(stream))!=EOF && i<MAXLEN; i++)
    {
        str[i]=buff;
    }

    for (int i = 0; str[i] != '\0'; )
    {
        buff=str[i];
        i++;
        for(int x=i; str[x]!='\0';x++)
        {
            if(buff == str[x])
            str[x]=EOF;
        }
    }


    for (int z = 0;str[z] != '\0' ; z++)
    {
        if(str[z] != EOF)
        printf("%c",str[z]);
    }

    return 0;
}
dron@gnu:~$ gcc -std=c99 del.c ; ./a.out 
asfdjhgner
dron@gnu:~$ 

Dron ★★★★★
()
Последнее исправление: Dron (всего исправлений: 1)
Ответ на: комментарий от ziemin

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

serles
() автор топика
Ответ на: комментарий от serles

А что бы в строках искал:

(echo "aabbcc"; echo "ddeeff") | (
  while read line
  do
    echo "$line" | sed "s/./&\n/g" | (
      while read c
      do
        if [ "${in[x$c]}" != "1" ]
        then
          in[x$c]=1
          echo -n $c
        fi
      done)
  done)

ziemin ★★
()
Ответ на: комментарий от serles

хрен с юникодом, забейте на него!

Работает же.

Помогите отсортировать символы построчно в файле

#! /usr/bin/perl

use 5.010;
use strict;
use warnings;
use utf8;
use open qw(:std :utf8);

while (<>) {
    chomp;
    my @letters = split //, $_;
    my @output;
    my %seen;

    for my $letter (@letters) {
	if (!defined $seen{$letter}) {
	    push @output, $letter;
	    $seen{$letter}++;
	} 
    }

    say sort @output;
}

Применять так:

user@host$ ./duplicates.pl input.txt

Чтобы писало вывод в файл:

user@host$ ./duplicates.pl input.txt > output.txt

Файл должен читаться построчно, 16Гб памяти иметь не обязательно.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от serles
#!/usr/bin/python3

enc = 'utf-8'
out = open('target.out', 'w', encoding=enc)
for line in open('target.in', 'r', encoding=enc):
    line = ''.join(sorted(set(line.rstrip('\r\n'))))
    out.write('%s\n' % line)
anonymous
()
Ответ на: комментарий от ziemin

@Nervous
Фантастика! 151М
real 1m28.737s
user 1m26.940s
sys 0m0.240s

@ziemin
Отлично работает, но очень медленно:
за пять минут только 800кб из 151М обработал
Ребята!
Огромнейшее вам всем спасибо!
Вы мне очень помогли!

serles
() автор топика
Ответ на: комментарий от serles

Говорят, что если сделать вот так, будет еще быстрее, но мне не на чем проверить.

#! /usr/bin/perl

use 5.010;
use strict;
use warnings;
use utf8;
use open qw(:std :utf8);

while (<>) {
    chomp;
    my @letters = unpack 'U*', $_;
    my @output;
    my %seen;

    for my $letter (@letters) {
	if (!defined $seen{$letter}) {
	    push @output, $letter;
	    $seen{$letter}++;
	} 
    }

    say pack 'U*', sort @output;
}
Nervous ★★★★★
()
Ответ на: комментарий от Nervous

но мне не на чем проверить.

#!/usr/bin/python3

import random

def lines():
    alpha = '1234567890' + \
        'qwertyuiopasdfghjklzxcvbnm' + \
        'QWERTYUIOPASDFGHJKLZXCVBNM' + \
        'йцукенгшщзхъфывапролджэячсмитьбюё' + \
        'ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ'
    while True:
        n = 50 + random.randrange(150)
        items = [random.choice(alpha) for _ in range(n)]
        yield ('%s\n' % ''.join(items)).encode('utf-8')

f = open('target.in', 'wb')
size = 0
for line in lines():
    if size >= 150*1024**2:
        break
    f.write(line)
    size = size + len(line)
anonymous
()
Ответ на: комментарий от serles

А вот это точно раза в 2 быстрее (спасибо анонимусу за данные для тестов).

#! /usr/bin/perl

use 5.010;
use strict;
use warnings;
use utf8;
use open qw(:std :utf8);
use List::MoreUtils qw(uniq);

while (<>) {
    chomp;
    my @letters = split //, $_;
    my @output = uniq @letters;
    say sort @output;
}
Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 2)
Ответ на: комментарий от Nervous

Да, ВЫ правы:

real 1m21.635s
user 1m11.952s
sys 0m0.228s

Ещё раз огромрое спасибо всем!

serles
() автор топика
Ответ на: комментарий от serles

то что ты делаешь nekulturno

порядок букв в ответе важен?

если нет добавь |sort по вкусу.

qulinxao ★★☆
()
Ответ на: комментарий от Nervous

Мда... Сейчас разобрался, опять не то:
Прекрасно удаляет дубликаты символов в строке, это гуд.
А что совсем есть не гуд, так это то, что он вдобавок сортирует по алфавиту символы в этой строке:

вход:

11111585
23414577
87645312

выход:

158
123457
12345678

а нужно:

158
234157
87645312



Что бы тупо удалял все повторяющиеся символы!

serles
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.