Как "двухпроходный" сценарий может поддерживать чтение ввода либо из файла, либо из стандартного ввода?

Я думаю, вы смешиваете rpc _pipefs с nfs .

rpc _pipefs — это помощник, необходимый для работы nfs, но он не является фактическим монтированием удаленного сервера nfs. В большинстве случаев его можно безопасно исключить из /etc/fstab (. Обычно правильные значения по умолчанию для rpc _pipef жестко запрограммированы в сценарии запуска nfs, который игнорирует /etc/fstab ).

Например, следующая строка взята из моего /etc/fstab (примечания nfs вместо rpc _pipefs в 3 -rd столбце):

192.168.200.1:/mnt/vg/git   /mnt/host/git   nfs  defaults       0 0
192.168.200.1:/mnt/vg/work  /mnt/host/work  nfs  nosuid,noexec  0 0
2
25.04.2020, 03:29
2 ответа

В общем случае, чтобы иметь возможность обрабатывать стандартный ввод более одного раза, вам нужно либо иметь возможность вернуться после первого чтения, либо прочитать его снова (, что возможно не для всех типов. файлов, например pipe, sockets, terminals )или сохраните этот ввод в обычном файле или памяти, где вы знаете, что можете прочитать его более одного раза.

Это проще сделать с оболочками со встроенным поиском и поддержкой управления временными файлами, такими как zsh или ksh93.

#! /bin/zsh -
zmodload zsh/system || exit

if (($#)); then
  # arguments are provided. They are assumed to be file arguments
  # to process (use./- for the file called -)
  grep -h -- '^#' "$@"
  grep -vh -- '^#' "$@" | sort
else
  # process stdin
  if (( (pos = systell(0)) >= 0 )); then
    # input is seekable
    grep '^#'
    sysseek $pos || {
      syserror -p "Cannot go back: "
      exit 1
    }
    grep -v '^#' | sort
  else
    # not seekable, store input in a temporary file using =(cat)
    () {
      grep -- '^#' $1
      grep -v -- '^#' $1
    } =(cat)
  fi
fi

(обратите внимание, что -hпропуск вывода имен файлов является расширением GNU grep; если ваш grepне поддерживает его, вы можете заменить его наcat -- "$@" | grep...).

bashне поддерживает ни поиск, ни создание временных файлов, но вы можете вызвать для этого zsh, ksh93или perl/ python.

Однако для вашего конкретного случая использования вы также можете:

#! /bin/sh -
gawk -e '
  /^#/ {print; next}
  {print | "sort"}' -E /dev/null "$@"

Трюк -e+ -Eнеобходим для обработки имен файлов, содержащих =символов (обратите внимание, что аргумент -по-прежнему интерпретируется gawkкак значение стандартного ввода, а не файла называется-).

Отсортированный выше вывод гарантированно будет отображаться после комментариев, поскольку sortнеобходимо прочитать все свои входные данные, прежде чем он сможет начать что-либо выводить. sortхранит данные в памяти или во временных файлах.

Подобные подходы:

#! /bin/zsh -
{ cat -- "$@" > >(grep '^#' 4>&1 >&3) | grep -v '^#' | sort; } 3>&1

Или для совместимости с ksh93 или bash:

{
  cat -- "$@" |
   { tee >(grep '^#' 4>&1 >&3); } |
   grep -v '^#' |
   sort
} 3>&1

Если вывод catравен tee, преобразованный как в grep, так и в grep -v | sort, это также должно работать. 4>&1используется, чтобы гарантировать, что sortне начнет вывод до того, как grepзакончит запись (, поскольку он также удерживает канал grep -vоткрытым во время работы ).

3
19.03.2021, 02:26

Просто sortчасть вывода, которую вы хотите отсортировать.grep -E '^#' "$INPUTFILE";(grep -E -v '^#' "$INPUTFILE" | sort )

-2
19.03.2021, 02:26

Теги

Похожие вопросы