LINUX.ORG.RU

[скриптота] Читать файл пословно


0

1

Лучше перлом.

Нужно читать файл не строками, а словами.
Про $/ в перле знаю, но между словами может быть пробелов больше одного.

Файл может быть очень большим, так что нужно считывать постепенно.
split строки тоже не годится.


Пример файла

 index1           index2            nc_td           adrv_cap          
                  iptr              cap_z           t_en0             
                  v_en0             t_en1           
                  alter#            
    1.000         1.000             3.01            5  
                  5.000             1.000           0             
                  failed            3.000           1             

    2.000         2.000             3.01            5  
                  5.000             failed          0             
                  0                 3.000           1   
    3.000         3.000             3.01            5      
                  5.000             4.000           0             
                  0                 3.000
                  1    
mosfet ()

> Про $/ в перле знаю, но между словами может быть пробелов больше одного.

-_-'

$ echo 'мама мыла   раму' | perl -nE 'BEGIN{$/=" "}s/\s//g;next unless length;say'
мама
мыла
раму
$ _
arsi ★★★★★ ()
Ответ на: комментарий от outsider

Перл при while(<IN>) заносит очередную строку в $_.
Так вот нужно чтобы заносил не строку, а слово. если $/=' ', то в $_ попадают лишние пробелы если их подряд больше одного. А сделать $/='\s+' не получается.

Пропускать лишние пробелы нельзя

mosfet ()
Ответ на: комментарий от arsi

если строки не сверхдлинные, то можно и проще:

perl -nE 'say for /\S+/g'
arsi ★★★★★ ()
Ответ на: комментарий от mosfet

> Пропускать лишние пробелы нельзя

это вообще как понимать? ты же собирался читать только слова, пропуская пробелы вообще… уточни задачу.

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

А чем так не годится?

Я так понимаю хочется чтобы все все все умел язык? ;) Напишите свой модуль для чтения по словам.

Кстати тут не обрабатываются заэскейпленые переносы строк - \

 

while(<IN>) { 
   foreach my $word (split /\s+/, $_) { 
      print "$word\n"; 
   } 
} 

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

> Имелось ввиду, что нельзя делать `next if ' '`

не внесло ясности. шеф запрещает? огласи весь список того, что нельзя делать. или список того, что можно, если он будет короче…

arsi ★★★★★ ()
irb(main):004:0> str = " index1           index2            nc_td           adrv_cap        "
=> " index1           index2            nc_td           adrv_cap        "
irb(main):005:0> str.split
=> ["index1", "index2", "nc_td", "adrv_cap"]
kovrik ★★★★★ ()
Ответ на: комментарий от kovrik

Хотелось просто процедуру-черный ящик, читающую словами. Видимо так просто не получиться.

В общем пока получилась как-то так

$/ = ' ';

sub get_next_word
{
    do { $_ = <IN> } while /^\s+$/;
    chomp;
    s/\n//;
    return $_
}
mosfet ()
Ответ на: комментарий от kovrik
file = File.new("input", "r")
arr = []
while (line = file.gets)
	line = line.split

	line.each do |w|
		puts w
	end
end
file.close
kovrik@casper:~/Desktop$ ruby parser2.rb 
index1
index2
nc_td
adrv_cap
iptr
cap_z
t_en0
v_en0
t_en1
alter#
1.000
1.000
3.01
5
5.000
1.000
0
failed
3.000
1
2.000
2.000
3.01
5
5.000
failed
0
0
3.000
1
3.000
3.000
3.01
5
5.000
4.000
0
0
3.000
1
kovrik ★★★★★ ()
Ответ на: комментарий от mosfet

А, понял, т.е. просто где-то происходит инициализация, открываем файл. А потом где-то в коде просто вызываем, например, parser.nextWord - и он нам возвращает слово следующее?

kovrik ★★★★★ ()
#!/bin/sh

for WORD in `cat /dev/stdin`; do
    echo $WORD
done
cat file.txt | ./r.sh 
index1
index2
nc_td
adrv_cap
iptr
cap_z
t_en0
v_en0
t_en1
alter#
1.000
1.000
3.01
5
5.000
1.000
0
failed
3.000
1
2.000
2.000
3.01
5
5.000
failed
0
0
3.000
1
3.000
3.000
3.01
5
5.000
4.000
0
0
3.000
1
dizza ★★★★★ ()
Ответ на: комментарий от dizza

Я так понял, что это решение не подойдет, ибо сразу выводит все, а ТС желает вызывать по 1 разу метод, который будет 1 слово возвращать.

kovrik ★★★★★ ()

for i in $(cat $file); do echo $i; done

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

Спасибо, а то у меня цикл никак останавливаться не хотел. А как ноль как строку возвращать для этого?

while(my $w = get_next_word())

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

> А как ноль как строку возвращать для этого?

while (length(my $w = get_next_word)) {
	...
}
arsi ★★★★★ ()
Ответ на: комментарий от mosfet
class ReadWord
  def initialize(filename)
    @file = File.new filename, "r"
    @line = []
  end

  def nextWord
    if @line.empty?
      @line = @file.gets
      if @line then
        @line = @line.split
      else
        @file.close
        return
      end
    end

    @line.shift
  end
end
do0dlez ★★ ()
Ответ на: комментарий от mosfet

Вот другой вариант, со сплитом.

{
 my %x;

 sub get_word
 {
   my $fd=shift || die ...;

   $x{$fd->fileno} ||= [];
   my $ref=   $x{$fd->fileno};

   if ( @$ref) {
     return shift @$ref;
   }
   else {
     while (!@$ref) {
        my $str=$fd->getline();
        
        if (!$str) {
          return undef; #eof
         }        

        chomp $str;
        @$ref=[split(/\s+/, $str)];        
     }
   }
 }

}
OxiD ★★★★ ()
Ответ на: комментарий от mosfet

Правильнее делать local $/=' ' и делать это внутри блока.. а то мало ли что случится )

OxiD ★★★★ ()

Я учту ваши предложения :)

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