나는 종종 동일한 패턴을 따르는 KSH 쉘 스크립트를 작성합니다.
- (1) 하나 이상의 명령 출력 검색
- (2) grep|cut|awk|sed를 사용하여 포맷하고 화면이나 파일에 인쇄합니다.
이를 위해 나는 종종 (1)의 출력을 임시 파일에 저장한 다음 (2)와 같이 파일 형식을 지정합니다.
다음 코드를 예로 들어 보겠습니다.
TMPFILE=file.tmp
# If tmpfile exists rm it.
[ -f $TMPFILE ] && rm -f $TMPFILE
for SERVICE in $(myfunc); do
getInfo $SERVICE > $TMPFILE # Store raw output in the TMPFILE
# I retrieve the relevant data from the TMPFILE
SERV_NAME=$(head -1 $TMPFILE | sed -e 's/ $//')
SERV_HOSTNAME=$(grep HOSTNAME $TMPFILE | cut -d "=" -f2)
SERV_ARGS=$(grep Arguments $TMPFILE | cut -d ":" -f2)
print $SERV_NAME $SEP $SERV_HOSTNAME $SEP $SERV_ARGS
rm -f $TMPFILE #rm the TMPFILE in vue of next iteration
done
매번 파일을 디스크에 쓰지 않도록 파이프, 리디렉션 등을 사용하는 방법이 있습니까?
도움이 된다면 ksh 버전 M-11/16/88i를 사용하고 있습니다.
답변1
귀하의 코드가 임시 파일을 완벽하게 합법적으로 사용하고 있는 것 같습니다. 저는 이 방법을 고수하겠습니다. 정말로 변경해야 할 유일한 것은 임시 파일이 생성되는 방식입니다. 다음과 같은 것을 사용하십시오
TMP=$(tempfile)
또는
TMP=$(mktemp)
아니면 적어도
TMP=/tmp/myscript_$$
이렇게 하면 이름을 쉽게 예측할 수 있고(안전하게) 동시에 실행되는 여러 스크립트 인스턴스 간의 간섭을 배제할 수 없습니다.
답변2
변수를 사용할 수 있습니다.
info="$(getInfo $SERVICE)"
SERV_NAME="$(head -1 $TMPFILE <<<"$info" | sed -e 's/ $//')"
...
에서 man ksh
:
<<<word A short form of here document in which word becomes the
contents of the here-document after any parameter expan-
sion, command substitution, and arithmetic substitution
occur.
장점은 다음과 같습니다:
- 병렬 실행을 활성화합니다.
- 내 경험상 이것은 임시 파일보다 훨씬 빠릅니다. 데이터가 너무 많아서 교체가 필요할 정도가 아니라면 속도는 훨씬 더 빨라야 합니다(작은 데이터 크기의 경우 더 빠를 수 있는 HD 캐시 버퍼만 제외).
- 다른 프로세스나 사용자가 귀하의 데이터를 망칠 수 없습니다.
답변3
두 가지 옵션이 있습니다:
데이터를 한 번(예제에서
getInfo
) 검색하여 파일에 저장합니다.데이터는 매번 가져오며 로컬에 저장되지 않습니다. 즉,
getInfo
호출될 때마다
재처리/다시 가져오기를 방지하기 위해 임시 파일을 생성하는 데 문제가 없습니다.
임시 파일을 어딘가에 남겨두는 것이 걱정된다면 trap
스크립트가 종료/중단되는 경우 항상 삭제했는지 확인하는 데 사용할 수 있습니다.
trap "rm -f $TMPFILE" EXIT HUP INT QUIT TERM
mktemp
임시 파일의 고유한 파일 이름을 만드는 데 사용됩니다 .
답변4
파일을 생성하는 대신 쉘 할당문을 구성하고 출력을 평가합니다.
for SERVICE in $(myfunc); do
eval $(getInfo $SERVICE |
sed -n -e '1/\(.*\) *$/SERV_NAME="\1"/p' \
-e '/HOSTNAME/s/^[^=]*=\([^=]*\).*/SERV_HOSTNAME="\1"/p' \
-e '/Arguments/^[^:]*:\([^:]*\).*/SERV_ARGS="\1"/p')
print $SERV_NAME $SEP $SERV_HOSTNAME $SED $SERV_ARGS
done
또는 정보만 인쇄하려는 경우:
for SERVICE in $(myfunc); do
getInfo $SERVICE | awk -vsep="$SEP" '
BEGIN{OFS=sep}
NR == 1 { sub(/ *$/,""); SERV_NAME=$0 }
/HOSTNAME/ { split($0, HOST, /=/; SERV_HOSTNAME=HOST[2]; }
/Arguments/ { split($0, ARGS, /:/; SERV_ARGS }
END { print SERV_NAME, SERV_HOSTNAME, SERV_ARGS }'
done