Решено: построчное чтение файла. как?

Модератор: Модераторы разделов

Kornelius
Сообщения: 86
ОС: Linux/BSD/Netware/OpenSolaris

Решено: построчное чтение файла. как?

Сообщение Kornelius »

Всем драсте.

Подскажите как на bash'e реализовать следующее.

Есть файл input.txt такого содержания:
string1
string2
string3
string4

Нужно написать скрипт, который за один запуск извлечет из файла строку string1 и запишет ее в output.txt. Следующий запуск извлечет из файла строку string2 и запишет ее в output.txt.
Таким образом после 2-ух запусков у нас будет такое содержимое файлов:
input.txt
---------
string3
string4

output.txt
---------
string1
string2


Нужно именно на BASHе.
(Очень желательно оптимальный код)
Заранее спасибо.
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Решено: построчное чтение файла. как?

Сообщение allez »

А в чем сакральный смысл данного действа? Или это вам такое задание в учебном заведении дали? Если да, то читайте про sed и перенаправление вывода в файл.
Спасибо сказали:
Kornelius
Сообщения: 86
ОС: Linux/BSD/Netware/OpenSolaris

Re: Решено: построчное чтение файла. как?

Сообщение Kornelius »

allez писал(а):
03.01.2009 23:09
А в чем сакральный смысл данного действа? Или это вам такое задание в учебном заведении дали?



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

allez писал(а):
03.01.2009 23:09
Если да, то читайте про sed и перенаправление вывода в файл.


sed? Чем он мне поможет вырезать(удалить) первую строку из файла, не трогая все остальные строки. Ведь их может быть очень много.

Проблема у меня именно в удалении первой строки из файла.
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Решено: построчное чтение файла. как?

Сообщение allez »

Kornelius писал(а):
03.01.2009 23:18
sed? Чем он мне поможет вырезать(удалить) первую строку из файла, не трогая все остальные строки. Ведь их может быть очень много.
Читайте man sed на предмет команды "d".

Навскидку пока могу предложить это:

Код: Выделить всё

cat file | sed -n '1p' >> output.txt; sed -i '1d' file
Спасибо сказали:
Аватара пользователя
Reboot
Сообщения: 321
Статус: Красен глаз -- темна душа

Re: Решено: построчное чтение файла. как?

Сообщение Reboot »

Kornelius, если FIFO в виде файла, то все просто, после прочтения всё само умрёт. head -n 1 например достаточно. или седом
Мой компьютер зовут Марвин
Спасибо сказали:
Kornelius
Сообщения: 86
ОС: Linux/BSD/Netware/OpenSolaris

Re: Решено: построчное чтение файла. как?

Сообщение Kornelius »

Читайте man sed на предмет команды "d".

Навскидку пока могу предложить это:

Код: Выделить всё

cat file | sed -n '1p' >> output.txt; sed -i '1d' file



cat file однозначно не катит, скрипт возможно будет вызываться несколько раз в секунду и обрабатывать файлик, содержащий тысячу строк. Система ляжет.

А на счет команды "d" щас почитаем.

Reboot писал(а):
03.01.2009 23:25
Kornelius, если FIFO в виде файла, то все просто, после прочтения всё само умрёт. head -n 1 например достаточно. или седом



Как так само? Поясните плз.
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Решено: построчное чтение файла. как?

Сообщение allez »

Kornelius писал(а):
03.01.2009 23:28
cat file однозначно не катит

Код: Выделить всё

sed -n '1p' file >> output.txt; sed -i '1d' file
Можно так, но не факт, что это будет намного быстрее.
Спасибо сказали:
Аватара пользователя
Reboot
Сообщения: 321
Статус: Красен глаз -- темна душа

Re: Решено: построчное чтение файла. как?

Сообщение Reboot »

файлик используется в качестве буфера(FIFO)

если это так, то почему бы не использовать непосредственно FIFO файл?
man fifo
Мой компьютер зовут Марвин
Спасибо сказали:
Kornelius
Сообщения: 86
ОС: Linux/BSD/Netware/OpenSolaris

Re: Решено: построчное чтение файла. как?

Сообщение Kornelius »

Я вообче надаялся, что может есть утиль какая для этого.
Видимо придется самому на C написать.
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Решено: построчное чтение файла. как?

Сообщение diesel »

Kornelius писал(а):
03.01.2009 23:02
Всем драсте.
....


вообще напоминает вопрос на контрольной, которых мы не любим :)

Ненадежный способ(то есть если в строках есть спецсимволы которые могут интепретироваться как куски регулярного выражения что-то может пойти не так; если строки повторяются, то тоже пойдет не так)

Код: Выделить всё

#!/bin/bash

cat input.txt | while read i; do
    grep -E "^$i$" output.txt || {
            echo $i >> output.txt
            sed -i -e "/$i/d" input.txt
            break
        }
    done
Спасибо сказали:
Kornelius
Сообщения: 86
ОС: Linux/BSD/Netware/OpenSolaris

Re: Решено: построчное чтение файла. как?

Сообщение Kornelius »

Reboot писал(а):
03.01.2009 23:31
файлик используется в качестве буфера(FIFO)

если это так, то почему бы не использовать непосредственно FIFO файл?
man fifo


Спасибо за вариант - надо обдумать.
Хотя скорее всего не подойдет по причине возможной потери данных в случае сбоя, зависания
компа и т.п. Файлик как то надежнее.
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Решено: построчное чтение файла. как?

Сообщение diesel »

Kornelius писал(а):
03.01.2009 23:28
Читайте man sed на предмет команды "d".

Навскидку пока могу предложить это:

Код: Выделить всё

cat file | sed -n '1p' >> output.txt; sed -i '1d' file



cat file однозначно не катит, скрипт возможно будет вызываться несколько раз в секунду и обрабатывать файлик, содержащий тысячу строк. Система ляжет.


убери cat. можно sed -n '1p' filename
Спасибо сказали:
Kornelius
Сообщения: 86
ОС: Linux/BSD/Netware/OpenSolaris

Re: Решено: построчное чтение файла. как?

Сообщение Kornelius »

diesel писал(а):
03.01.2009 23:32
Kornelius писал(а):
03.01.2009 23:02
Всем драсте.
....


вообще напоминает вопрос на контрольной, которых мы не любим :)

Ненадежный способ(то есть если в строках есть спецсимволы которые могут интепретироваться как куски регулярного выражения что-то может пойти не так; если строки повторяются, то тоже пойдет не так)

Код: Выделить всё

#!/bin/bash

cat input.txt | while read i; do
    grep -E "^$i$" output.txt || {
            echo $i >> output.txt
            sed -i -e "/$i/d" input.txt
            break
        }
    done




Интересный вариант. А Вы случайно не знаете как действует эта схема с pipe - в смысле файл input.txt сразу будет прочитан илил постепенно считываться порциями и что будет если во время работы этого скрипта в файл будут продолжать писаться данные.
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Решено: построчное чтение файла. как?

Сообщение diesel »

Kornelius писал(а):
03.01.2009 23:43
Интересный вариант. А Вы случайно не знаете как действует эта схема с pipe - в смысле файл input.txt сразу будет прочитан илил постепенно считываться порциями и что будет если во время работы этого скрипта в файл будут продолжать писаться данные.

скорее всего будет прочитан как только так сразу. лучше вариант с sed'ом - если предполагается что это надо часто и быстро. Как вариант sed '1p' можно использовать head -1 filename(данные ведь пишутся в конец файла?)
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Решено: построчное чтение файла. как?

Сообщение allez »

Kornelius писал(а):
03.01.2009 23:28
скрипт возможно будет вызываться несколько раз в секунду и обрабатывать файлик, содержащий тысячу строк. Система ляжет.

сравнение быстродействия с cat и без оного

03:39 home:~/tmp $ wc -l file 1523 file 03:39 home:~/tmp $ time ( sed -n '1p' file >> output.txt; sed -i '1d' file ) real 0m0.062s user 0m0.036s sys 0m0.020s 03:39 home:~/tmp $ time ( sed -n '1p' file >> output.txt; sed -i '1d' file ) real 0m0.059s user 0m0.040s sys 0m0.020s 03:39 home:~/tmp $ time ( sed -n '1p' file >> output.txt; sed -i '1d' file ) real 0m0.059s user 0m0.048s sys 0m0.012s 03:39 home:~/tmp $ time ( cat file | sed -n '1p' >> output.txt; sed -i '1d' file ) real 0m0.070s user 0m0.032s sys 0m0.032s 03:39 home:~/tmp $ time ( cat file | sed -n '1p' >> output.txt; sed -i '1d' file ) real 0m0.069s user 0m0.028s sys 0m0.028s 03:39 home:~/tmp $ time ( cat file | sed -n '1p' >> output.txt; sed -i '1d' file ) real 0m0.066s user 0m0.032s sys 0m0.024s

Как видим, на обработку файла в полторы тысячи строк уходит меньше одной десятой секунды. Процессор - AMD Athlon™ 64 X2 Dual Core Processor 4200+.
Спасибо сказали:
Kornelius
Сообщения: 86
ОС: Linux/BSD/Netware/OpenSolaris

Re: Решено: построчное чтение файла. как?

Сообщение Kornelius »

allez писал(а):
03.01.2009 23:46
Как видим, на обработку файла в полторы тысячи строк уходит меньше одной десятой секунды. Процессор - AMD Athlon™ 64 X2 Dual Core Processor 4200+.


ОК. Буду пробовать :)
Всем спасибо и за опцию "d" в сиде отдельное спасибо. Надо маны лучше курить, полагаю что
сид можно будет ограничить удалением первой найденой строки, а не всех подобных строк во всем файле.

Жалко правда что нет такой утилиты и приходится огород городить, а я так надеялся.
Спасибо сказали:
Kornelius
Сообщения: 86
ОС: Linux/BSD/Netware/OpenSolaris

Re: Решено: построчное чтение файла. как?

Сообщение Kornelius »

Нашел приемлемое решение.
Если вдруг кому будет интересно, то вот:

Код: Выделить всё

head -n 1 input.txt>>output.txt; sed -i "1d" input.txt


или лучше:

Код: Выделить всё

sed "q" input.txt>>output.txt; sed -i "1d" input.txt


Спасибо allezу


Если бы можно было упростить до:

Код: Выделить всё

sed -i "1d" input.txt>>output.txt

то было бы самое то что нужно.
Спасибо сказали:
Аватара пользователя
кодировщик
Сообщения: 974
Статус: зарёган в пятницу 13
ОС: Linux

Re: Решено: построчное чтение файла. как?

Сообщение кодировщик »

А можно это как модифицировать чтобы вывести случайную строку?!
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Решено: построчное чтение файла. как?

Сообщение diesel »

кодировщик писал(а):
09.01.2009 22:51
А можно это как модифицировать чтобы вывести случайную строку?!


если не думать:

Код: Выделить всё

rand=$(perl -e "print int(rand($(wc -l $filename|awk '{print $1}')))" ); sed -n "${rand}p" $filename
Спасибо сказали:
Аватара пользователя
кодировщик
Сообщения: 974
Статус: зарёган в пятницу 13
ОС: Linux

Re: Решено: построчное чтение файла. как?

Сообщение кодировщик »

diesel писал(а):
09.01.2009 23:25
кодировщик писал(а):
09.01.2009 22:51
А можно это как модифицировать чтобы вывести случайную строку?!


если не думать:

Код: Выделить всё

rand=$(perl -e "print int(rand($(wc -l $filename|awk '{print $1}')))" ); sed -n "${rand}p" $filename


неа, чот не выходит.
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Решено: построчное чтение файла. как?

Сообщение diesel »

кодировщик писал(а):
10.01.2009 23:20
diesel писал(а):
09.01.2009 23:25
кодировщик писал(а):
09.01.2009 22:51
А можно это как модифицировать чтобы вывести случайную строку?!


если не думать:

Код: Выделить всё

rand=$(perl -e "print int(rand($(wc -l $filename|awk '{print $1}')))" ); sed -n "${rand}p" $filename


неа, чот не выходит.

что конкретно?

Код: Выделить всё

diesel@debian:/tmp$ filename=test.txt
diesel@debian:/tmp$ rand=$(perl -e "print int(rand($(wc -l $filename|awk '{print $1}')))+1" ); echo $rand; sed -n "${rand}p" $filename
2
string2
diesel@debian:/tmp$ rand=$(perl -e "print int(rand($(wc -l $filename|awk '{print $1}')))+1" ); echo $rand; sed -n "${rand}p" $filename
3
string3
diesel@debian:/tmp$ cat test.txt
string1
string2
string3
string4
Спасибо сказали: