Форум русскоязычного сообщества Ubuntu


Автор Тема: простой вопрос по bash  (Прочитано 1926 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн jo80

  • Автор темы
  • Любитель
  • *
  • Сообщений: 52
    • Просмотр профиля
простой вопрос по bash
« : 17 Декабрь 2016, 21:15:47 »
Господа!
у меня есть потребность в консоли обработать и перезаписать текстовый файл, делаю я это с помощью bash , но к сожалению конструкция типа:

cat ./f | grep "ddd" > ./f

не работает и приходится вводить промежуточный файл  ./a  т.е. я делаю так:

cat ./f  | grep "ddd" > ./a
cat ./a > ./f

Введение промежуточного файла мне вообще не нравиться, но ведь наверняка это можно сделать без промежуточного файла? каким образом это можно сделать?
« Последнее редактирование: 17 Декабрь 2016, 21:27:24 от jo80 »

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #1 : 17 Декабрь 2016, 21:27:43 »
Например так:
d="$(grep "ddd" f)" ; echo "$d" > f

Оффлайн jo80

  • Автор темы
  • Любитель
  • *
  • Сообщений: 52
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #2 : 17 Декабрь 2016, 21:34:48 »
Благодарю за ответ. Но конструкция какая то не обычная,  что то меня берут сомнения будет ли она работать с большими объёмами данных? И если допустим в место grep мне нужно туда целый конвеер из программ вставить сработает ли она?
« Последнее редактирование: 17 Декабрь 2016, 21:39:32 от jo80 »

Оффлайн snowin

  • Активист
  • *
  • Сообщений: 603
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #3 : 17 Декабрь 2016, 21:40:03 »
jo80,
попробуй так
sed '/ddd/!d' ./f

если выдаст желаемое, тогда можешь добавить параметр "-i", который перезапишет файл ./f
sed -i '/ddd/!d' ./f

а если добавить к параметру ".bck", то старый файл будет переименован (сохранен) с расширением "bck"
sed -i.bck '/ddd/!d' ./f

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #4 : 17 Декабрь 2016, 21:45:56 »
jo80,
Если объем большой тогда лучше так:
tmp_file="$(mktemp -u --tmpdir="$PWD")" ; grep "ddd" file > tmp_file ; mv tmp_file file

Оффлайн ALiEN175

  • Старожил
  • *
  • Сообщений: 2200
  • X-9000SC
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #5 : 17 Декабрь 2016, 21:46:26 »
Код: Bash
  1. cat ./f | grep "ddd" | tee ./f
Благодарности на Yandex 41001488642430. Cпасибо.

Оффлайн jo80

  • Автор темы
  • Любитель
  • *
  • Сообщений: 52
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #6 : 17 Декабрь 2016, 21:57:11 »
Благодарю всех за ответы, особено ALiEN175 .

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #7 : 17 Декабрь 2016, 22:01:59 »
Цитировать
cat ./f | grep "ddd" | tee ./f
Только cat и ./ не нужно.
grep "ddd" file | tee fileили
grep "ddd" file | tee file >/dev/null

Оффлайн ALiEN175

  • Старожил
  • *
  • Сообщений: 2200
  • X-9000SC
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #8 : 17 Декабрь 2016, 22:05:05 »
renzrv, разница есть. Конструкция
grep "ddd" file | tee file
у меня не заработала. Подозреваю, причина в количестве конвейеров.

То есть читаем файл - грепаем строчки - пишем файл. А не грепаем файл и сразу в тот же файл пишем, который грепаем.

« Последнее редактирование: 17 Декабрь 2016, 22:12:09 от ALiEN175 »
Благодарности на Yandex 41001488642430. Cпасибо.

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #9 : 17 Декабрь 2016, 22:20:07 »
ALiEN175,
Потестил, пару раз сработало и без cat, но потом почему-то и c cat, и без файл становится пустым. sync не помог. Вобщем не вариант.

Оффлайн ALiEN175

  • Старожил
  • *
  • Сообщений: 2200
  • X-9000SC
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #10 : 17 Декабрь 2016, 22:47:03 »
renzrv, для повторного использования переименуйте файл  :)
Благодарности на Yandex 41001488642430. Cпасибо.

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #11 : 17 Декабрь 2016, 23:06:17 »
ALiEN175,
Перед каждым запуском содержимое file восстанавливаю. Дело не в этом.
Тест:
cp file.bkp file ; sync ; cat file | grep PATTERN file | tee file
В file 20 строк, грепится 2 строки.
file.bkp - копия для восстанавления.
Срабатывает (записываются 2 строки) как-то через раз, рандомно. Несрабатывает - делает файл пустым.
« Последнее редактирование: 17 Декабрь 2016, 23:08:39 от renzrv »

Оффлайн ALiEN175

  • Старожил
  • *
  • Сообщений: 2200
  • X-9000SC
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #12 : 17 Декабрь 2016, 23:24:52 »
renzrv,

Код: Bash
  1. cp file.bkp file && sync && cat file | grep PATTERN | tee file

В grep имя файла не надо.
И точно, если вместе с sync - можно не переименовывать =)

я сейчас затестил - ничего не пропало:
Код: Bash
  1. for i in {1..50} ; do cp file.bkp file && sync && cat file | grep PATTERN | tee file > /dev/null ; done && cat file
« Последнее редактирование: 17 Декабрь 2016, 23:34:39 от ALiEN175 »
Благодарности на Yandex 41001488642430. Cпасибо.

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #13 : 17 Декабрь 2016, 23:43:34 »
Цитировать
В grep имя файла не надо.
Не надо, верно. Это я скопировал не то. Но все так же работает через раз, делая файл пустым.

Цитировать
То есть читаем файл - грепаем строчки - пишем файл. А не грепаем файл и сразу в тот же файл пишем, который грепаем.
При запуске команд в конвеере все команды стартуют одновременно (почти), в этом и вся фишка.
Если раньше стартанет grep - то будет вывод и сработает.
Но если раньше стартанет tee - то не сработает, т.к - он сделает файлу - turncate, grep ничего не найдет, и файл будет пустым.

Нашел решение:
Код: Bash
  1. grep PATTERN file | (sleep 0.1 ; tee file)

Оффлайн ALiEN175

  • Старожил
  • *
  • Сообщений: 2200
  • X-9000SC
    • Просмотр профиля
Re: простой вопрос по bash
« Ответ #14 : 17 Декабрь 2016, 23:56:54 »
Хм, может от быстродействия зависит? У меня файлопомойка с торентами на древнем компе - с десяток раз эту команду использовал, ничего не пропадало. Тем не менее, решение - супер. Как я сам не догадался) 

Кстати, там же команду выше в цикле запускал - нормально все отработало.
« Последнее редактирование: 18 Декабрь 2016, 00:00:10 от ALiEN175 »
Благодарности на Yandex 41001488642430. Cпасибо.

 

Страница сгенерирована за 0.094 секунд. Запросов: 24.