awk 스크립트의 파이핑

awk 스크립트의 파이핑

의 출력을 구문 분석하는 데 ls사용되는 래퍼를 작성하려고 합니다 . 지금은 프로그램을 두 개의 파일 과 . 의 유일한 목적은 의 출력 을 . 그것은 다음과 같습니다:awkls -lhFmy_ls.shmy_ls.awkmy_ls.shls -lhFmy_ls.awk

#!/bin/bash
ls -lhF "$@" | my_ls.awk

ls -lhFawk 스크립트 자체를 통해 출력을 읽을 수 있는 방법이 있는지 궁금합니다 .

편집하다:나의 주요 목적은 현재 디렉토리 내용을 멋진 트리 형태로 보여주는 스크립트를 작성하는 것입니다. 초안 버전은 my_ls.awk다음과 같습니다.

#!/usr/bin/awk -f

( NF >= 9 ) {
    print "|-- [" $5 "] " $9
}

이것내가 지금까지 도달한 곳은 여기이다.

답변1

의 출력을 구문 분석하면 안 된다는 다른 조언에 동참하겠습니다 ls. 따라서 이는 나쁜 예입니다. 그러나 보다 일반적인 문제로서 awk 스크립트를 awk.

#!/bin/bash
ls -lhF "$@" | awk '
    ( NF >= 9 ) {
        print "|-- [" $5 "] " $9
    }'

awk 스크립트에 '(작은 따옴표) 문자가 포함되어야 하는 경우 이를 인용해야 합니다. '\''(닫는 작은 따옴표, 리터럴 작은 따옴표, 여는 작은 따옴표)를 사용하십시오.

인용하지 않으려면 다음을 사용할 수 있습니다.여기 문서대신에. 하지만 표준 입력을 사용하여 awk에 입력을 제공하고 스크립트를 제공할 수 없기 때문에 어색합니다. 추가 파일 설명자를 사용해야 합니다(참조:추가 파일 설명자는 언제 사용합니까? 파일 설명자 및 쉘 스크립팅).

#!/bin/bash
ls -lhF "$@" | awk -f /dev/fd/3 3<<'EOF'
( NF >= 9 ) {
    print "|-- [" $5 "] " $9
}
EOF

getlineawk 내에서 함수와 파이프 구성을 사용하여 다른 명령의 입력을 읽을 수 있습니다 . awk가 기본적으로 사용하도록 설계된 방식은 아니지만 작동하도록 만들 수 있습니다. 오류가 발생하기 쉬운 기본 셸에 대한 파일 이름 인수를 인용해야 합니다. 그리고 처리할 텍스트가 예상 소스(표준 입력 또는 명령줄에 명명된 파일)에서 나오지 않기 때문에 결국 블록에 모든 코드가 포함됩니다 BEGIN.

#!/usr/bin/awk -f
BEGIN {
    command = "ls -lhF"
    for (i = 1; i <= ARGC; i++) {
        arg = ARGV[i];
        gsub("'", "'\\''", arg);
        command = command " '" arg "'";
    }
    ARGC = 0; for (i in ARGV) delete ARGV[i];
    while ((command | getline) > 0) {
        if (NF >= 9) { print "|-- [" $5 "] " $9 }
    }
}

간단히 말해서, 쉘이 잘하는 것(예: 명령을 함께 파이핑하는 것)에는 쉘을 사용하고, 잘하는 것(예: 텍스트 처리)에는 awk를 사용하십시오.

답변2

무엇을 하려는지 잘 모르겠지만 발생할 수 있는 한 가지 문제는 마지막 필드로 간주되지만 그렇게 간주되지 않는 awk필드(기본 구문 분석을 통해)를 인쇄하는 것 입니다. 예. lsawk

-rw-r--r-- | 433k | filename-with-no-spaces      
-rw-r--r-- |   1k | link containing  spaces -> /home/user/filename-with-no-spaces

어떻게든 마지막 필드를 분리해야 합니다 ls. 아래에서 취한 접근 방식은 모든 이전 필드와 구분 기호의 길이를 찾는 것입니다. 나머지는 파일 이름 필드(링크 대상과 같은 기타 정보 포함)입니다. 

아래 스크립트는 가변 너비의 최대 너비를 결정합니다.크기필드(출력 형식화에 필요) 이 너비를 얻는 방법에는 여러 가지가 있습니다. 예.(1)awk메인 루프에서 출력 의 각 라인을 처리 ls 하고 후속 처리를 위해 각 라인을 배열에 추가하는 데 사용됩니다 END{ }. 또는(2) 출력을 ls임시 파일에 쓴 다음 awk해당 파일을 처리하도록 합니다. 아래에 표시된 방법은 다음을 사용합니다.(2).

ls의 경우와 같이 의 출력은 예상치 못한, 단순하지 않은 결과를 원하는 방식으로 보낼 수 있으므로 일반적 으로 구문 분석 요구 사항에 더 적합하도록 출력을 link사용하고 사용자 정의하는 것이 더 안전합니다 .find

f=7               # the number of (multi-space) delimiters before the start of the filename  
myls="$(mktemp)"  # a temp file to hold  output from `ls`
w=$(ls --color=always -lFHk ~/ |tee "$myls" |awk '{print $5}' |wc -L) # max width of size field
h=k               # size unit
awk --re-interval -v"f=$f" -v"w=$w" -v"h=$h" '
  NF >= f {
    regex = "^([^ ]+ +){"f"}" 
    match( $0, regex )  # find start of name field
    printf( "%s | %"w"s%s | %s\n", $1, $5, h, substr( $0, RLENGTH ))
  }' "$myls"
rm "$myls"

답변3

바퀴를 재발명하는 것을 피하고 대신 tree디렉토리의 파일/폴더 및 하위 디렉토리 파일/폴더를 표시하는 를 사용하는 것이 좋습니다.

tree(1) - Linux 매뉴얼 페이지

이름

tree - 트리와 같은 형식으로 디렉토리 내용을 나열합니다.

개요

tree [-adfghilnopqrstuvxACDFNS] [-L 수준 [-R]] [-H baseHREF] [-T 제목] [-o 파일 이름] [--nolinks] [-P 패턴] [-I 패턴] [--inodes] [ --device] [--noreport] [--dirsfirst] [--version] [--help] [--filelimit #] [디렉토리 ...]

설명

Tree는 깊이 들여쓰기된 파일 목록을 생성하는 재귀적 디렉터리 목록 프로그램입니다. LS_COLORS 환경 변수가 설정되고 출력이 tty로 이루어지며 -C 플래그가 사용되는 경우 색상은 dircolors와 같이 지원됩니다. 인수가 없으면 tree는 현재 디렉터리의 파일을 나열합니다. 디렉토리 인수가 주어지면 tree는 주어진 디렉토리에서 발견된 모든 파일 및/또는 디렉토리를 차례로 나열합니다. 발견된 모든 파일/디렉터리 나열이 완료되면 tree는 나열된 파일 및/또는 디렉터리의 총 수를 반환합니다.

기본적으로 기호 링크가 발견되면 기호 링크가 참조하는 경로가 링크 이름 뒤에 다음 형식으로 인쇄됩니다.

이름 -> 실제 경로

'-l' 옵션이 주어지고 심볼릭 링크가 실제 디렉토리를 참조하면 tree는 마치 실제 디렉토리인 것처럼 심볼릭 링크의 경로를 따릅니다.

관련 정보