pilcrow's answer обеспечивает элегантное решение; это объяснение , почему подход OP не работал.
Основная проблемы с подходом ФПА в была попытки присвоить позиционного параметра $1
с $1=...
, который не будет работать.
и LHS расширяется за счет оболочки к значению из $1
, а результат интерпретируется как имя переменной присвоить - понятно, не намерения.
единственный способ назначить $1
в Баш через set
встроено. Предостережение заключается в том, что set
неизменно устанавливает все позиционные параметры, поэтому вам нужно включить и другие, если они есть.
set -- "${1:-/dev/stdin}" "${@:2}" # "${@:2}" expands to all remaining parameters
(Если вы ожидаете только в самых аргумент, set -- "${1:-/dev/stdin}"
будет делать.)
Вышесказанное также корректирует вторичную проблему с подходом ОП в: попытка для хранения содержимого, а не на имени файла из стандартного ввода в $1
, так как <
используются.
${1:-/dev/stdin}
является применение Баш parameter expansion, который говорит: возвращает значение $1
, если $1
не определено (не был принят ни один аргумент) или его значение является пустой строкой (""
или ''
был принят). Изменение ${1-/dev/stdin}
(без :
) возвращать только бы /dev/stdin
если $1
является неопределенными (если он содержит любого значения, даже пустую строку, она будет возвращена).
Если мы соберем все вместе:
# Default to filename '/dev/stdin' (stdin), if none was specified.
set -- "${1:-/dev/stdin}" "${@:2}"
while read -r line; do
... # find the longest line
done < "$1"
Но, конечно, гораздо более простой подход будет использовать ${1:-/dev/stdin}
в качестве имени файла непосредственно:
while read -r line; do
... # find the longest line
done < "${1:-/dev/stdin}"
или через промежуточная переменная:
filename=${1:-/dev/stdin}
while read -r line; do
... # find the longest line
done < "$filename"
возможно дубликат [Баш чтение из файла или стандартного ввода] (http://stackoverflow.com/questions/6980090/bash-read-from-file- or-stdin) – Oswald