변수가 변경되면 문자열에서 bash 매개변수를 평가하는 방법

변수가 변경되면 문자열에서 bash 매개변수를 평가하는 방법

이것을 어떻게 설명해야 할지 잘 모르겠지만, 제가 하고 있는 일을 설명하려고 노력하겠습니다. 나는 BASH문자열을 전달하는 방법을 알아내려고 벽에 머리를 기대고 있었습니다 . {command:$1}스크립트에 추가하고 $1해당 값으로 채워지도록 합니다.

내가 시도하고 싶은 것은 출력을 json으로 변환하고, 스크립트를 사용하여 구문 분석하고 형식을 지정하고, 키와 값을 설정한 lsof다음 원하는 열을 얻는 것입니다.awk

내 스크립트

#!/bin/bash

FORMAT=$1
(
IFS=' ';
while read line; do
    set -- $line;
    echo $FORMAT
done
)

내 명령줄 호출

lsof -Pn | grep LISTEN | awk '{print $1,$2,$3,$4,$5,$8,$9}' | ~/.scripts/json "{command:\$1,pid:\$2,user:\$3,fd:\$4,protocol:\$5:\$6,host:\$7}"

내 귀환

{command:$1,pid:$2,user:$3,fd:$4,protocol:$5:$6,host:$7}

슬래시를 제거하면

{command:,pid:,user:,fd:,protocol::,host:}

내가 뭘 기대하는 거지?

{command:webstorm,pid:5270,user:daviddiefenderfer,fd:142u,protocol:IPv4:TCP,host:127.0.0.1:6942}

정확히 무슨 일이 일어나고 있는지는 모르겠지만 이해하고 싶습니다. 변수는 $[1-7]값이 없는 while 루프에 들어가기 전에 평가되고 있는 것 같습니다.

답변1

당신은 바퀴를 재발명하고 있습니다(그리고 잘못되었습니다). JSON을 생성하는 데 사용됩니다 jq.

 lsof -Pn | 
   awk '/LISTEN/ {print $1,$2,$3,$4, $5,$8,$9}' |
   jq -R 'split(" ") |
         {
           command: .[0],
           pid: .[1],
           user: .[2],
           fd: .[3],
           protocol: "\(.[4]):\(.[5])", 
           host: .[6]
         }'

귀하의 버전이 jq정규식을 지원하는 경우 다음에 대한 호출을 제거할 수도 있습니다 awk.

lsof -Pn | jq -R '
  select(match("LISTEN")) |
  [splits("  *")] |
  {
    command: .[0],
    pid: .[1],
    user: .[2],
    fd: .[3],
    protocol: "\(.[4]):\(.[7])", 
    host: .[8]
  }'

답변2

$1, $2, ...awk의 필드 접근자를 쉘의 $1, $2, ...위치 매개변수 와 혼동하고 있습니다 . 게다가 파이프라인은 위치 매개변수를 설정하지 않고 단순히 왼쪽의 출력을 오른쪽의 입력으로 제공합니다.

JSON에는 객체 속성 이름을 포함하여 따옴표로 묶인 문자열 값이 필요하다는 점을 잊지 마세요.

json=$(
    lsof -Pn | grep LISTEN \
    | awk '
        BEGIN {template = "{\"command\":\"%s\",\"pid\":\"%s\",\"user\":\"%s\",\"fd\":\"%s\",\"protocol\":\"%s:%s\",\"host\":\"%s\"}\n"}
        {printf template, $1, $2, $3, $4, $5, $8, $9}
    '
)
~/.scripts/json "$json"

관련 정보