1

Здравствуйте!
Столкнулся со следующей проблемой:
Есть текст, разделенный символами табуляции. Количество символов табуляции в разных строках варьируется.
Как с помощью адресации sed можно отобрать строки, содержащие только 6 символов табуляции? Следует учесть, что символы tab не обязательно идут друг за другом подряд, т.е. между ними может быть текст.

Пробовал использовать такой вариант:

sed -e "/\(\t[^\t]*\)\{6\}/!d"

пока не помогает. Скорее всего, я неправильно написал регулярное выражение.
буду дальше думать
PS: просьба не бить сильно руками,  использовал GNU sed version 4.0.7 под win32 из unixutils.

2

Я бы определял число одинаковых символов в строке с помощью awk,
используя его как этот символ как разделитель. Например, если надо
найти число символов 'f' в переменной $str, то выражение

`echo $str | awk -F "f" '{printf("%d",NF)}'`

вернет число, на 1 больше.

Пётр.

Пётр.

3 (19.12.2013 22:34:42 отредактировано moshell)

#!/usr/bin/perl

while (<>) {
    chomp;
    if ( /^([^\t]*\t){6}[^\t]*$/ ) {
        print "Matched: |$`<$&>$'|\n";
    }
}

### для проверки
# сохраните этот кусок кода в какой нибудь файл с именем any_file
chmod +x any_file
./any_file text_for_parsing
# где text_for_parsing - это текст в котором хотите найти эти 6 табуляторов

"Фирма Майкрософт не собирается поддерживать протокол TCP/IP в своих OS" 1993 (c) Билл Гейтс
"Мы изобрели новый протокол передачи данных, мы назвали его TCP/IP" 1995 (c) Билл Гейтс

4

spronkin1 пишет:

пока не помогает. Скорее всего, я неправильно написал регулярное выражение.

да нет... вроде всё правильно, если «не меньше 6 табов» надо (если надо ровно 6, то сопри регулярку у moshell'а)... разве что в bash пытается интерпретировать восклицательный знак, так что надо писать в одинарных кавычках... или эскейпить...

spronkin1 пишет:

PS: просьба не бить сильно руками,  использовал GNU sed version 4.0.7 под win32 из unixutils.

а как sed запускается? из bash'а? или из cmd? если второе? если второе, то не знаю как он символы эскейпит... но сдаётся мне, что везде нужен дополнительный бекслеш... а может и два...

95% процентов проблем находятся между клавиатурой и стулом.

5 (20.12.2013 02:02:01 отредактировано spronkin1)

moshell пишет:

#!/usr/bin/perl

while (<>) {
    chomp;
    if ( /^([^\t]*\t){6}[^\t]*$/ ) {
        print "Matched: |$`<$&>$'|\n";
    }
}

Нужен именно однострочник на sed. sed из пакета unixutils запускается из cmd. Можно в linux, главное, чтобы это был однострочник на sed.
PS: и еще: каждая строка начинается с символа tab

6

spronkin1 пишет:

Нужен именно однострочник на sed

regexp Вам уже дан. включите мозг и перефразируйте его на sed. не всю же жизнь зависеть от кого то

spronkin1 пишет:

запускается из cmd.

вот тут различия будут. в какой ОС вы работаете.

spronkin1 пишет:

Можно в linux, главное, чтобы это был однострочник на sed.

это к доктору, скоро он придет.

spronkin1 пишет:

каждая строка начинается с символа tab

а я дал универсальный ответ. не за что.

"Фирма Майкрософт не собирается поддерживать протокол TCP/IP в своих OS" 1993 (c) Билл Гейтс
"Мы изобрели новый протокол передачи данных, мы назвали его TCP/IP" 1995 (c) Билл Гейтс

7 (20.12.2013 19:15:17 отредактировано spronkin1)

moshell пишет:

regexp Вам уже дан. включите мозг и перефразируйте его на sed. не всю же жизнь зависеть от кого то

Спасибо за разъяснения. Буду думать, как это реализовать под win32 - нужно, на работе win32, дома linux, поэтому запускаю из wineconsole cmd, конечно, это изврат, но я боюсь, что если я этот скрипт буду реализовывать в native shell, то могу допустить ошибки в win32, например, в виде одинарных кавычек или отсутствия экранирования символов. По-видимому, у меня какой-то глюкодром с cmd.

cat serv2.txt | sed -e "s/\t/qqq/g" > temp.txt

заменяет не символ табуляции, а букву t. Даже

sed -e "s/\x09/qqq/g" > temp.txt

не хочет заменять tab. Попробую еще сравнить как эти regexp будут работать под win32.

8 (20.12.2013 20:03:42 отредактировано moshell)

а зачем бояться? выполняйте. система (если она не на столько тупа) сама покажет Вам где ошибки


http://xpoint.ru/know-how/Perl/Podderzh … zhivayutsy

"Фирма Майкрософт не собирается поддерживать протокол TCP/IP в своих OS" 1993 (c) Билл Гейтс
"Мы изобрели новый протокол передачи данных, мы назвали его TCP/IP" 1995 (c) Билл Гейтс

9 (20.12.2013 23:21:07 отредактировано spronkin1)

moshell пишет:

http://xpoint.ru/know-how/Perl/Podderzh … zhivayutsy

К сожалению, я  пока не изучал Perl, но спасибо за ссылку,

spronkin1 пишет:

cat serv2.txt | sed -e "s/\t/qqq/g" > temp.txt

заменяет не символ табуляции, а букву t. Даже

sed -e "s/\x09/qqq/g" > temp.txt

не хочет заменять tab. Попробую еще сравнить как эти regexp будут работать под win32.

При выполнении указанных команд в cmd.exe под win32 sed отрабатывает успешно. По-видимому, это чистой воды косяк wineconsole cmd. Попробую еще с двойным экранированием \\, но я, конечно расстроен, что wine не поддерживает cmd так как надо в win32.

В win32 соответственно ваш regexp:

/^([^\t]*\t){6}[^\t]*$/

будет выглядеть так:

"/^\([^\t]*\t\)\{6\}[^\t]*$"

т.е. в sed.exe нужно брать regexp в двойные кавычки "" и, кроме этого, экранировать круглые и фигурные скобки с помощью \ (backslash), хотя значение этих костылей Винды для данного Форума не актуально ab
Мне пригодился ваш скрипт вот в таком случае: в строках, содержащих 8 разделителей, заменить 6 разделитель на 2 разделителя (\tab), с целью выравнивания текста относительно строк, содержащих 9 разделителей:

cat.exe "unalign.txt" | sed "/^\([^\t]*\t\)\{8\}[^\t]*$/s/\t/&&/6" > align.txt

Спасибо!

10 (21.12.2013 20:12:57 отредактировано smaharbA)

echo -e '1\t2\t3\t4\t5\t6\t7\n1\t2\t3\t4\t5\t6\n\t\t\t\t\t\t1\n' | sed '/\(.*[\t].*\)\{6\}/!d; /\(.*[\t].*\)\{7,\}/d;'
Я конечно далек от мысли...(с)