텍스트 파일은 키 값 형식에 따라 형식을 지정하고 업데이트해야 합니다.

텍스트 파일은 키 값 형식에 따라 형식을 지정하고 업데이트해야 합니다.

다음 값을 가진 파일이 있습니다.

고양이 데이터.txt

server1: calv
server2: anot
log: /u/log/1
server3: calv
server4: anot
server5: secd
server6: calv
LIB_TRGT_calv,anot: /tmp/hello.txt
LIB_TRGT_secd: /var/del.tmp

LIB_TRGTLIB_TRGT_calv,anotie &로 시작하는 변수를 얻습니다 .LIB_TRGT_secd

TRGT_위의 변수(예: calv,anot)에서 이름을 가져와야 합니다.

&가 있는 모든 항목을 가져 와서 다음과 같이 data.txt에 있는 항목을 추가 calv & anot해야 합니다 .calvanot

원하는 출력:

server1: calv
server2: anot
log: /u/log/1
server3: calv
server4: anot
server5: secd
server6: calv
LIB_TRGT_calv,anot: /tmp/hello.txt
LIB_TRGT_secd: /var/del.tmp
LIB_server1:  /tmp/hello.txt
LIB_server2:  /tmp/hello.txt
LIB_server3:  /tmp/hello.txt
LIB_server4:  /tmp/hello.txt
LIB_server6:  /tmp/hello.txt
LIB_server5: /var/del.tmp

동일LIB_TRGT_secd

지금까지 내가 한 일은 다음과 같습니다.

grep TRGT* data.txt | cut -d: -f1 |cut -d_ -f3
calv,anot
secd

더 멀리

grep TRGT* test.txt | cut -d: -f1 |cut -d_ -f3 | sed -n 1'p' | tr ',' '\n'
calv
anot

그러나 secd그것이 누락되어 있으며 이를 사용하고 추가로 처리하는 방법을 잘 모르겠습니다 xargs.

사용자 @Kusalananda의 솔루션을 시도했지만 작동하지 않았습니다. 아래 출력을 참조하세요.

여기에 이미지 설명을 입력하세요.

답변1

이 행이 항상 나타난다 awk고 가정하고 이를 수행하는 프로그램LIB_TRGT_뒤쪽에다음에 인용된 다른 줄은 다음과 같습니다.

BEGIN {
        FS = ":[[:blank:]]*"
        OFS = ": "
}

{ print }

$1 !~ /^LIB_TRGT_/ {
        # "list" is an associative array that uses the keys "calv",
        # "anot", and "secd", and for each of these stores the relevant
        # servers as a SUBSEP-delimited string.

        list[$2] = (list[$2] == "" ? $1 : list[$2] SUBSEP $1)
        next
}

{
        path = $2

        # Pick out the comma-delimited list of keys after "TRGT_", and
        # split these up into elements of the array "k".

        sub("^.*TRGT_", "", $1)
        nk = split($1, k, ",")

        $0 = ""
        $2 = path

        # For each key, get the corresponding list from "list" and
        # output the path for each of its values.

        for (i = 1; i <= nk; ++i) {
                nv = split(list[k[i]], v, SUBSEP)
                for (j = 1; j <= nv; ++j) {
                        $1 = "LIB_" v[j]
                        print
                }
        }
}

script데이터와 함께 파일에서 위 스크립트로 테스트하십시오.유닉스 텍스트 파일라고 불리는 file:

$ awk -f script file
server1: calv
server2: anot
log: /u/log/1
server3: calv
server4: anot
server5: secd
server6: calv
LIB_TRGT_calv,anot: /tmp/hello.txt
LIB_server1: /tmp/hello.txt
LIB_server3: /tmp/hello.txt
LIB_server6: /tmp/hello.txt
LIB_server2: /tmp/hello.txt
LIB_server4: /tmp/hello.txt
LIB_TRGT_secd: /var/del.tmp
LIB_server5: /var/del.tmp

순서는 질문에 표시된 것과 약간 다릅니다. 순서는 LIB_TRGT_저장하고 마지막에 처리하는 대신 나타나는 즉시 반응하기 때문입니다.

답변2

데이터에서 코드를 생성한 다음 생성된 코드를 데이터 자체에 적용하여 이 문제를 해결할 수 있습니다.

확장된 정규식 모드를 사용하는 GNU sed.

inputf='./data.txt'

< "$inputf" \
sed -E '
  s/^\s+|\s+$//g
  s/\s+/\t/g
' |
sed -E '
  /_TRGT_[^:\t]/{
    s/^(([^_]+_)+TRGT_)([^,:]+)[,:](.*(\t\S+))$/\3\5\n\1\4/
    h;s/\n.*//;s/.*\t//
    s:[\/&]:\\&:g;G
    s/(.*)\n(.*\t).*(\n.*)/\2\1\3/
    P
  }
  D
' |
sed -En '
  1i\
p

  s#(.*)\t(.*)#/:\\t\1$/{s/^/LIB_/;s/:.*/:\\t\2/;H;ba;}#p

  $a\
:a\
$!d;g;s/.//
' |
sed -Ef - "$inputf"

server1:    calv
server2:    anot
log:    /u/log/1
server3:    calv
server4:    anot
server5:    secd
server6:    calv
LIB_TRGT_calv,anot: /tmp/hello.txt
LIB_TRGT_secd:  /var/del.tmp
LIB_server1:    /tmp/hello.txt
LIB_server2:    /tmp/hello.txt
LIB_server3:    /tmp/hello.txt
LIB_server4:    /tmp/hello.txt
LIB_server5:    /var/del.tmp
LIB_server6:    /tmp/hello.txt

  • 0단계, 선행 및 후행 공백을 제거하여 데이터를 정리합니다. TAB에 고정 폭 글꼴.
  • 첫 번째 단계에서는 키-값 쌍을 분리하여 행당 하나씩 배치합니다.
  • 2단계 이러한 kv 튜플을 사용하여 sed 코드를 생성합니다.
  • 3단계, 데이터에 코드를 적용합니다.

답변3

다음은 두 경우, 즉 두 번째 필드가 참조되는지 여부에 대한 통합 솔루션입니다.

awk -v q=\' '1
NF<2{next}
!/^([^_]+_)+TRGT_/ {
  a[FNR] = $2
  b[FNR,$2] = $1
  if (index($2,q) == 1) quoted++
  next
}
{
  n = split($1, temp, /[_,:]/)
  s=0
  for (i=1; i<n; i++) {
    t = temp[i]
    s += length(t)+1
    ch = substr($1, s-1, 1)
    if (ch == "_") continue
    key = (!quoted) ? t : q t q
    c[key] = $2
  }
  split("", temp, ":")
}
BEGIN { OFS="\t" }
END {
  for (i=1; i in a; i++)
    if ( (a[i] in c) && ((i SUBSEP a[i]) in b))
      print "LIB_"b[i,a[i]], c[a[i]]
}' data.txt

server1:    'calv'
server2:    'anot'
log:    '/u/log/1'
server3:    'calv'
server4:    'anot'
server5:    'secd'
server6:    'calv'
LIB_TRGT_calv,anot: '/tmp/hello.txt'
LIB_TRGT_secd:  '/var/del.tmp'
LIB_server1:    '/tmp/hello.txt'
LIB_server2:    '/tmp/hello.txt'
LIB_server3:    '/tmp/hello.txt'
LIB_server4:    '/tmp/hello.txt'
LIB_server5:    '/var/del.tmp'
LIB_server6:    '/tmp/hello.txt'

관련 정보