파일 이름 인수 또는 stdin의 입력을 허용하는 스크립트를 어떻게 작성할 수 있습니까?
예를 들어이 less
방법을 사용할 수 있습니다 . 하나를 실행 less filename
하고 동등하게 수행 할 수 있습니다 cat filename | less
.
"상자 밖으로"쉽게 할 수있는 방법이 있습니까? 또는 바퀴를 다시 발명하고 스크립트에 약간의 논리를 작성해야합니까?
파일 이름 인수 또는 stdin의 입력을 허용하는 스크립트를 어떻게 작성할 수 있습니까?
예를 들어이 less
방법을 사용할 수 있습니다 . 하나를 실행 less filename
하고 동등하게 수행 할 수 있습니다 cat filename | less
.
"상자 밖으로"쉽게 할 수있는 방법이 있습니까? 또는 바퀴를 다시 발명하고 스크립트에 약간의 논리를 작성해야합니까?
답변:
파일 인수가 스크립트의 첫 번째 인수 인 경우 인수 ( $1
)가 있고 파일인지 테스트 하십시오. stdin에서 다른 읽기 입력-
따라서 스크립트에는 다음과 같은 내용이 포함될 수 있습니다.
#!/bin/bash
[ $# -ge 1 -a -f "$1" ] && input="$1" || input="-"
cat $input
예를 들어 다음과 같이 스크립트를 호출 할 수 있습니다
./myscript.sh filename
또는
who | ./myscript.sh
스크립트에 대한 설명을 편집하십시오 .
[ $# -ge 1 -a -f "$1" ]
-하나 이상의 명령 행 인수 ( $# -ge 1
) AND (-연산자)가 첫 번째 인수가 파일 인 경우 ( "$ 1"이 파일 인 경우 -f 테스트) 테스트 결과는 참입니다.
&&
쉘 논리 AND 연산자입니다. 테스트가 참이면 파일 을 할당 input="$1"
하고 cat $input
출력합니다.
||
쉘 논리 OR 연산자입니다. 테스트가 거짓이면 다음 명령 ||
이 구문 분석됩니다. 입력은 "-"에 할당됩니다. 명령 cat -
은 키보드에서 읽습니다.
요약하면, 스크립트 인수가 제공되고 파일 인 경우 변수 입력이 파일 이름에 지정됩니다. 유효한 인수가 없으면 cat은 키보드에서 읽습니다.
&& input="$1" || input="-"
하며 왜 test
운영자 외부에 있습니까?
$@
)가있는 경우 어떻게합니까?
read
표준 입력에서 읽습니다. 파일 ( ./script <someinput
) 또는 파이프 ( dosomething | ./script
)를 통해 리디렉션하면 다르게 작동하지 않습니다.
입력의 모든 줄을 반복하기 만하면됩니다 (파일의 줄을 반복하는 것과 다르지 않습니다).
(샘플 코드, 한 줄만 처리)
#!/bin/bash
read var
echo $var
표준 입력의 첫 번째 줄을 통해 (에코 <
또는 |
) 에코합니다 .
어떤 쉘을 사용할 계획인지 언급하지 않았으므로 bash를 가정 할 것입니다.하지만 쉘 전체에서 꽤 표준적인 것들입니다.
변수를 통해 인수에 액세스 할 수 있습니다 $1
.- $n
( $0
프로그램을 실행하는 데 사용되는 명령을 반환합니다). cat
구분 기호가있는 n 개의 파일을 구분 하는 스크립트가 있다고 가정 해보십시오 .
#!/usr/bin/env bash
#
# Parameters:
# 1: string delimiter between arguments 2-n
# 2-n: file(s) to cat out
for arg in ${@:2} # $@ is the array of arguments, ${@:2} slices it starting at 2.
do
cat $arg
echo $1
done
이 경우 파일 이름을 cat로 전달합니다. 그러나 파일에서 데이터를 명시 적으로 쓰거나 다시 쓰지 않고 변환하려면 파일 내용을 변수에 저장할 수도 있습니다.
file_contents=$(cat $filename)
[...do some stuff...]
echo $file_contents >> $new_filename
stdin에서 읽는 한, 대부분의 쉘에는 표준이 read
내장되어 있지만 프롬프트를 지정하는 방법에는 차이가 있습니다 (최소한).
배쉬 사람 페이지가 내장 명령 의 꽤 간결한 설명을 가지고 read
,하지만 난 좋아 배쉬 해커 페이지를.
간단히:
read var_name
여러 변수를 설정하려면 다음과 같이 여러 매개 변수 이름을 제공하십시오 read
.
read var1 var2 var3
read
그런 다음 stdin에서 하나의 단어를 각 변수에 배치하고 나머지 모든 단어를 마지막 변수에 덤프합니다.
λ read var1 var2 var3
thing1 thing2 thing3 thing4 thing5
λ echo $var1; echo $var2; echo $var3
thing1
thing2
thing3 thing4 thing5
변수보다 적은 단어가 입력되면 남은 변수는 비어 있습니다 (이전에 설정 한 경우에도).
λ read var1 var2 var3
thing1 thing2
λ echo $var1; echo $var2; echo $var3
thing1
thing2
# Empty line
-p
프롬프트에 자주 플래그를 사용 합니다.
read -p "Enter filename: " filename
참고 : ZSH 및 KSH (및 기타)는 프롬프트에 다른 구문을 사용합니다.
read "filename?Enter filename: " # Everything following the '?' is the prompt
이것은 실제로 read
속임수가 아니지만와 함께 많이 사용합니다 read
. 예를 들면 다음과 같습니다.
read -p "Y/[N]: " reply
reply=${reply:-N}
기본적으로 변수 (답변)가 존재하면 자체를 반환하지만 비어 있으면 다음 매개 변수 ( "N")를 반환합니다.
가장 간단한 방법은 stdin을 직접 리디렉션하는 것입니다.
if [ "$1" ] ; then exec < "$1" ; fi
또는 더 간결한 형태를 선호하는 경우 :
test "$1" && exec < "$1"
이제 나머지 스크립트는 stdin에서 읽을 수 있습니다. 물론 파일 이름의 위치를로 하드 코딩하는 대신 고급 옵션 구문 분석을 사용하여 비슷하게 수행 할 수 있습니다 "$1"
.
exec
여기서 우리가 원하지 않는 명령으로 인수를 실행하려고 시도합니다.
if [ "$1" ] ; then exec < "$1" ; fi
테스트 스크립트로 복사 했는데 명령이 알 수 없기 때문에 오류 메시지가 표시됩니다. 간결한 형태와 동일합니다.
이미 이런 식으로 동작하는 다른 것을 사용 (또는 연결 해제) "$@"
텍스트의 공백을 탭으로 대체하는 도구를 작성하려고한다고 가정 해 봅시다.
tr
이 작업을 수행하는 가장 확실한 방법이지만 stdin 만 허용하므로 연결을 끊어야합니다 cat
.
$ cat entab1.sh
#!/bin/sh
cat "$@"|tr -s ' ' '\t'
$ cat entab1.sh|./entab1.sh
#!/bin/sh
cat "$@"|tr -s ' ' '\t'
$ ./entab1.sh entab1.sh
#!/bin/sh
cat "$@"|tr -s ' ' '\t'
$
사용되는 도구가 이미 이런 식으로 동작하는 예를 들어, sed
대신 다음 과 같이 다시 구현할 수 있습니다 .
$ cat entab2.sh
#!/bin/sh
sed -r 's/ +/\t/g' "$@"
$
당신은 또한 할 수 있습니다 :
#!/usr/bin/env bash
# Set variable input_file to either $1 or /dev/stdin, in case $1 is empty
# Note that this assumes that you are expecting the file name to operate on on $1
input_file="${1:-/dev/stdin}"
# You can now use "$input_file" as your file to operate on
cat "$input_file"
uglifyjs < /dev/stdin
하고 있으며 훌륭하게 작동합니다!
간단하게 유지 하고이 코드를 사용할 수도 있습니다
이 코드 를 사용하여 스크립트 파일 pass_it_on.sh 를 만들면
#!/bin/bash
cat
당신은 실행할 수 있습니다
cat SOMEFILE.txt | ./pass_it_on.sh
stdin의 모든 내용은 단순히 화면으로 퍼져 나옵니다.
또는이 코드를 사용하여 stdin 사본을 파일에 보관 한 다음 화면에 뿌립니다.
#!/bin/bash
tmpFile=`mktemp`
cat > $tmpFile
cat $tmpFile
여기에 더 읽기 쉬운 또 다른 예가 있습니다.
http://mockingeye.com/blog/2013/01/22/reading-everything-stdin-in-a-bash-script/
#!/bin/bash
VALUE=$(cat)
echo "$VALUE"
즐기세요
라미