У меня есть каталог, который содержит файлы журналов, я хочу совместить шаблон, чтобы удалить его, и снова записать содержимое в те же файлы [duplicate]

Зачем вы делаете while True, а затем выходите из этого цикла, в то время как вы также можете просто поместить свои требования в оператор while, поскольку все, что вы хотите, останавливается, когда у вас есть возраст?

age = None
while age is None:
    input_value = input("Please enter your age: ")
    try:
        # try and convert the string input to a number
        age = int(input_value)
    except ValueError:
        # tell the user off
        print("{input} is not a number, please enter a number only".format(input=input_value))
if age >= 18:
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")

Это приведет к следующему:

Please enter your age: *potato*
potato is not a number, please enter a number only
Please enter your age: *5*
You are not able to vote in the United States.

это будет работать, поскольку возраст никогда не будет иметь значения, которое не имеет смысла, а код следует логике вашего «бизнес-процесса»

166
задан Alex Dupuy 7 March 2014 в 12:01
поделиться

13 ответов

Если вы действительно хотите просто использовать sed -i «простой» способ, следующие работы работают как на GNU, так и на BSD / Mac sed:

sed -i.bak 's/foo/bar/' filename

Обратите внимание на нехватку места и точка.

Доказательство:

# GNU sed
% sed --version | head -1
GNU sed version 4.2.1
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

# BSD sed
% sed --version 2>&1 | head -1
sed: illegal option -- -
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

Очевидно, вы могли бы просто удалить файлы .bak.

132
ответ дан rogerdpack 20 August 2018 в 14:50
поделиться
  • 1
    Это путь. Добавьте несколько символов, и он переносится. Удаление файла резервной копии является тривиальным (у вас уже есть имя файла при вызове sed) – slezica 24 June 2015 в 21:10
  • 2
    Это работало на mac, но на ubuntu 16.04 он перезаписывал исходный файл в 0 байт и создает файл .bak также с 0 байтами? – house9 27 October 2016 в 18:22
  • 3
    Следует отметить, что в macOS Sierra (и, возможно, раньше у меня нет машины), sed не принимает аргумент positional command при вызове с -i - it must be с другим флагом -e. Таким образом, команда становится: sed -i.bak -e 's/foo/bar/' filename – ELLIOTTCABLE 16 May 2017 в 19:22
  • 4
    Это создает резервные копии, в то время как OP специально требует редактирования на месте. – Marc-André Lafortune 21 September 2017 в 23:43
  • 5
    Таким образом, полное решение: sed -i.bak 's/foo/bar/' file && rm file.bak – joeytwiddle 13 March 2018 в 05:02

Нет способа заставить его работать.

Один из способов - использовать временный файл, например:

TMP_FILE=`mktemp /tmp/config.XXXXXXXXXX`
sed -e "s/abc/def/" some/file > $TMP_FILE
mv $TMP_FILE some/file

Это работает как на

17
ответ дан analogue 20 August 2018 в 14:50
поделиться
  • 1
    Есть ли причина, по которой SOME_FILE = & quot; $ (sed -s "/ abc / def /" some / file) & quot ;; echo & quot; $ SOME_FILE & quot; & GT; некоторые / файл; не будет работать вместо этого – Jason Gross 12 December 2013 в 19:47
  • 2
    Похоже, вы ограничены максимальным размером переменной bash, нет? Не уверен, что он будет работать с файлами GB. – analogue 1 January 2014 в 16:56
  • 3
    Если вы создаете временный файл, почему бы просто не дать расширение для создания файла резервной копии (который вы затем можете удалить), как предлагает @kine ниже? – Alex Dupuy 7 March 2014 в 12:06

Ответ Стива Пауэлла совершенно верный, консультирование на странице MAN для sed на OSX и Linux (Ubuntu 12.04) подчеркивает совместимость в режиме «на месте» в двух операционных системах.

JFYI, не должно быть пробелов между -i и любыми кавычками (которые обозначают пустое расширение файла), используя версию sed для Linux, таким образом

sed Linux Man Страница

#Linux
sed -i"" 

и

sed OSX Man page

#OSX (notice the space after the '-i' argument)
sed -i "" 

Я обошел это в скрипт с помощью команды alias'd и вывода OS-имени «uname» в bash «if». Попытка хранить OS-зависимые командные строки в переменных была удалена и пропущена при интерпретации кавычек. Использование «shopt -s expand_aliases» необходимо для расширения / использования псевдонимов, определенных в вашем скрипте. Использование магазина {g3] здесь .

10
ответ дан Community 20 August 2018 в 14:50
поделиться

В Linux и OS X работает следующее:

sed -i' ' <expr> <file>

, например. для файла f, содержащего aaabbaaba

sed -i' ' 's/b/c/g' f

, выдается aaaccaaca как на Linux, так и на Mac. Обратите внимание, что имеется строка с кавычками , содержащая пробел , при этом нет пробела между -i и строкой. Одинарные или двойные кавычки работают.

В Linux я использую bash версию 4.3.11 под Ubuntu 14.04.4 и на Mac версии 3.2.57 под OS X 10.11.4 El Capitan (Darwin 15.4 0,0).

1
ответ дан David G 20 August 2018 в 14:50
поделиться
  • 1
    Вау, я рад, что я не слушал всех выше, говоря, что это невозможно и продолжал читать! Это действительно работает. Благодаря! – Personman 18 May 2016 в 19:25
  • 2
    Не работает для меня в Mac OS ... создается новый файл с пространством, добавленным в конец имени файла – Frédéric 29 August 2016 в 20:51
  • 3
    Не работает для меня на Mac (/ usr / bin / sed) - теперь у меня есть дополнительный файл резервной копии с пространством, добавленным к имени файла :-( – paul_h 5 February 2018 в 13:19

Вы можете использовать губку. Sponge - старая программа unix, найденная в пакете moreutils (как в ubuntu, так и, вероятно, в debian, и в homebrew в mac).

Он будет буферизовать все содержимое из канала, дождитесь закрытия канала (возможно, это значит, что входной файл уже закрыт), а затем перезапишите:

Из man page :

Сводка

sed '...' file | grep '...' | файл губки

0
ответ дан Guillermo 20 August 2018 в 14:50
поделиться
  • 1
    Приятный подход - к сожалению, не очень помогает в исходной ситуации, так как причиной прибегания к sed было использование чего-то в кросс-платформенном вспомогательном скрипте, используемом на клиентских машинах, где вы не можете зависеть ни от чего другого, кроме системы устанавливаемых инструментов. Однако может быть полезно кому-то другому. – klickverbot 7 August 2013 в 18:03
  • 2
    Губка великолепна. – paul_h 5 February 2018 в 13:16

Вот еще одна версия, которая работает на Linux и macOS без использования eval и без необходимости удалять файлы резервных копий. Он использует массивы Bash для хранения параметров sed, которые чище, чем использование eval:

# Default case for Linux sed, just use "-i"
sedi=(-i)
case "$(uname)" in
  # For macOS, use two parameters
  Darwin*) sedi=(-i "")
esac

# Expand the parameters in the actual call to "sed"
sed "${sedi[@]}" -e 's/foo/bar/' target.file

Это не создает файл резервной копии, ни файл с добавленными кавычками.

0
ответ дан nwinkler 20 August 2018 в 14:50
поделиться

Если вам нужно сделать sed на месте в сценарии bash, и вы НЕ хотите, чтобы на месте было результат с .bkp-файлами, и у вас есть способ обнаружить os (скажем, используя ostype.sh ), - тогда следующий хак с встроенной bash оболочкой eval должен работать:

OSTYPE="$(bash ostype.sh)"

cat > myfile.txt <<"EOF"
1111
2222
EOF

if [ "$OSTYPE" == "osx" ]; then
  ISED='-i ""'
else # $OSTYPE == linux64
  ISED='-i""'
fi

eval sed $ISED 's/2222/bbbb/g' myfile.txt
ls 
# GNU and OSX: still only myfile.txt there

cat myfile.txt
# GNU and OSX: both print:
# 1111
# bbbb

# NOTE: 
# if you just use `sed $ISED 's/2222/bbbb/g' myfile.txt` without `eval`,
# then you will get a backup file with quotations in the file name, 
# - that is, `myfile.txt""`
0
ответ дан sdaau 20 August 2018 в 14:50
поделиться

Это работает с GNU sed, но не на OS X:

sed -i -e 's/foo/bar/' target.file
sed -i'' -e 's/foo/bar/' target.file

Это работает на OS X, но не с GNU sed:

sed -i '' -e 's/foo/bar/' target.file

В OS X вы

  • не можете использовать sed -i -e, так как расширение файла резервной копии будет установлено на -e
  • , не может использовать sed -i'' -e по тем же причинам -It требуется пространство между -i и ''.
90
ответ дан slhck 20 August 2018 в 14:50
поделиться
  • 1
    что делает? – Alexander Mills 25 December 2016 в 21:39
  • 2
    @AlexanderMills Сообщает sed, что следующий аргумент является командой - также можно пропустить здесь. – Benjamin W. 21 January 2017 в 21:15

Когда в OSX я всегда устанавливаю версию GNU sed через Homebrew, чтобы избежать проблем с скриптами, потому что большинство скриптов были написаны для версий GNU sed.

brew install gnu-sed --with-default-names

Затем ваше BSD sed будет заменено на GNU sed.

В качестве альтернативы вы можете установить без имен по умолчанию, но затем:

  • Измените свой PATH, как указано после установки gnu-sed
  • Проверьте свои сценарии, чтобы выбрать между gsed или sed в зависимости от вашей системы
31
ответ дан slm 20 August 2018 в 14:50
поделиться

Ответ: Нет.

Первоначально принятый ответ фактически не выполняет то, что запрашивается (как отмечено в комментариях). (Я нашел этот ответ, когда искал причину, по которой file-e появлялся «случайно» в моих каталогах.)

По-видимому, нет способа заставить sed -i работать последовательно как на MacOS, так и на Linuces.

Моя рекомендация, для того, что она стоит, заключается не в обновлении с помощью sed (который имеет сложные режимы сбоя), а для создания новых файлов и последующего их переименования. Другими словами: избегайте -i.

12
ответ дан Steve Powell 20 August 2018 в 14:50
поделиться

Параметр -i не является частью POSIX Sed . Более переносимым способом было бы использовать Vim в режиме Ex:

ex -sc '%s/alfa/bravo/|x' file
  1. % выбрать все строки
  2. s заменить
  3. x сохранить и закрыть
4
ответ дан Steven Penny 20 August 2018 в 14:50
поделиться

Я столкнулся с этой проблемой. Единственным быстрым решением было заменить sed в mac на версию gnu:

brew install gnu-sed
3
ответ дан vikrantt 20 August 2018 в 14:50
поделиться
11
ответ дан Community 31 October 2018 в 11:13
поделиться