2013-10-27 4 views
8

Сценарий не работает, когда я хочу использовать стандартный ввод, если нет аргументов (файлов). Есть ли способ использования stdin вместо файла в этом коде?Как читать stdin, когда аргументы не передаются?

Я попытался это:

if [ ! -n $1 ] # check if argument exists 
    then 
    $1=$(</dev/stdin) # if not use stdin as an argument 
    fi 

var="$1" 
while read line 
    do 
    ...    # find the longest line 
    done <"$var" 
+3

возможно дубликат [Баш чтение из файла или стандартного ввода] (http://stackoverflow.com/questions/6980090/bash-read-from-file- or-stdin) – Oswald

ответ

6

Просто заменить Баш-х специально интерпретированы /dev/stdin как имя файла:

VAR=$1 
while read blah; do 
    ... 
done < "${VAR:-/dev/stdin}" 

(Обратите внимание, что баш будет реально использовать, что специальный файл/dev/stdinif built for an OS that offers it, но так как Баш 2,04 будет работать вокруг отсутствие этого файла на системах, которые делают не поддерживает)

1

Переменные присваивается значение по Var=Value и что переменная используется, например, echo $Var. В вашем случае это будет

1=$(</dev/stdin) 

при назначении стандартного ввода. Однако я не думаю, что имена переменных можно начинать с символа цифры. См. Вопрос bash read from file or stdin о способах решения этой проблемы.

+0

Действительно: '1' не является допустимым именем переменной в bash. Кроме того, единственный способ присвоить значения позиционным параметрам '$ 1',' $ 2', ... - использовать 'set' builtin (' set - ... '). – mklement0

0

Вот моя версия скрипта:.

#!/bin/bash 
file=${1--} # POSIX-compliant; ${1:--} can be used either. 
while IFS= read -r line; do 
    printf '%s\n' "$line" 
done < <(cat -- "$file") 

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

Другие примеры: How to read from file or stdin in bash? на StackOverflow SE

0

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" 
7

Для общего случая, когда вы хотите прочитать значение из stdin при отсутствии параметра, это будет работать.

$ echo param | script.sh 
$ script.sh param 

script.sh

#!/bin/bash 

set -- "${1:-$(</dev/stdin)}" "${@:2}" 

echo $1 
+0

Я предпочитаю это решение для цикла, потому что вам не нужно внедрять свою логику в любой внешний код. –

+0

'set - $ {@: - $ ( bishop

Смежные вопросы