Примените команду «expand» к файлу на месте, например sed -i

Примените команду «expand» к файлу на месте, например sed -i

Команда expandне имеет эквивалента

sed -i <file>

expandна самом деле есть -iвозможность - но это означает,

только после пробелов

Существует ли sedдинамическое expandдуэтное сочетание для достижения той же цели?

решение1

Утилита GNU expand не обеспечивает обновление 'in place', как sed. Воспроизвести тот же результат довольно просто, хотя команда может быть немного длиннее.

Невозможно одновременно анализировать и обновлять файл в произвольной файловой системе без риска повреждения, и по этой и другим причинам sed на самом деле этого не делает, хотя и абстрагирует это от пользователя. Что делает sed, и вы можете воспроизвести это самостоятельно, так это сохраняет вывод своей операции над объектным файлом во временном файле, затем удаляет исходную копию и переименовывает временный файл в исходный.

Есть несколько способов сделать это, вот один из них — файл с именем orig.txt — это файл, который «расширяется»:

tmp=`mktemp` && expand orig.txt > "$tmp" && mv "$tmp" orig.txt

Если вы никогда не используете никаких аргументов, кроме имени файла, для расширения, простая функция с именем expandможет скрыть весь временный файл в исходном файле подкачки и воспроизвести sedповедение — эта реализация будет принимать один аргумент путь/имя файла

expand() {
  [[ "$#" -ne "1" ]] && { echo "A single argument must be provided"; exit 1; }
  tmp=`mktemp` && expand "$1" > "$tmp" && mv "$tmp" "$1"
}

С небольшим изменением мы можем воссоздать всю expandфункциональность, поддерживая аргументы. Есть небольшая хитрость в захвате последнего аргумента, чтобы мы знали имя файла объекта, чтобы мы могли в конечном итоге перезаписать его выводом expand. Последний аргумент упоминается как ${@ -1}.

expand() {
      [[ "$#" -lt "1" ]] && { echo "At least a file name argument must be provided"; exit 1; }
      # Here we capture the last argument which is the object file name
      fname="${@: -1}"
      # The upcoming call to expand passes on all arguments including the file name
      tmp=`mktemp` && expand "$@" > "$tmp" && mv "$tmp" "$fname"
    }

Я не тестировал этот код, поэтому прошу прощения, если я не заметил синтаксическую ошибку.

Одну из этих функций или их версию следует поместить в .bashrcэквивалентный файл, который будет использоваться при создании новой оболочки, чтобы она была легкодоступна.

Если вы хотите иметь возможность указать, будет ли файл обновляться «на месте» или обновление будет отправлено в stdout, этот шаблон функции можно изменить так, чтобы он делал это на основе дополнительного аргумента (который не передается в expand, но изменяет способ вызова expand). Я не уверен, что вы ищете это, но я думаю, что у вас есть вся необходимая информация, чтобы сделать это сейчас, если вы ищете.

Или для большего удовольствия загрузите GNU coreutilsисходный кодиисходный код sed, проверьте, как sed справляется с этим, и перенесите этот код в вашу новую улучшенную версию expand. Отправьте это изменение обратно сопровождающим, и вы, возможно, упростите это для всех будущих пользователей 'expand'.

Связанный контент