sed 또는 awk 없이 출력에서 ​​특정 열을 쉽게 가져옵니다.

sed 또는 awk 없이 출력에서 ​​특정 열을 쉽게 가져옵니다.

sedand를 사용하는 것보다 여러 값 열을 얻는 더 빠른 방법이 있습니까 awk?

예를 들어, 출력이 있고 ls -hal /파일 및 디렉터리 이름과 크기만 가져오려는 경우 어떻게 해야 합니까?용이하게그리고빠르게명령을 수정하는 데 몇 분을 소비하지 않고도 이 작업을 수행할 수 있습니다.

total 16078
drwxr-xr-x    33 root  wheel   1.2K Aug 13 16:57 .
drwxr-xr-x    33 root  wheel   1.2K Aug 13 16:57 ..
-rw-rw-r--     1 root  admin    15K Aug 14 00:41 .DS_Store
d--x--x--x     8 root  wheel   272B Jun 20 16:40 .DocumentRevisions-V100
drwxr-xr-x+    3 root  wheel   102B Mar 27 12:26 .MobileBackups
drwx------     5 root  wheel   170B Jun 20 15:56 .Spotlight-V100
d-wx-wx-wt     2 root  wheel    68B Mar 27 12:26 .Trashes
drwxrwxrwx     4 root  wheel   136B Mar 30 20:00 .bzvol
srwxrwxrwx     1 root  wheel     0B Aug 13 16:57 .dbfseventsd
----------     1 root  admin     0B Aug 16  2012 .file
drwx------  1275 root  wheel    42K Aug 14 00:05 .fseventsd
drwxr-xr-x@    2 root  wheel    68B Jun 20  2012 .vol
drwxrwxr-x+  289 root  admin   9.6K Aug 13 10:29 Applications
drwxrwxr-x     7 root  admin   238B Mar  5 20:47 Developer
drwxr-xr-x+   69 root  wheel   2.3K Aug 12 21:36 Library
drwxr-xr-x@    2 root  wheel    68B Aug 16  2012 Network
drwxr-xr-x+    4 root  wheel   136B Mar 27 12:17 System
drwxr-xr-x     6 root  admin   204B Mar 27 12:22 Users
drwxrwxrwt@    6 root  admin   204B Aug 13 23:57 Volumes
drwxr-xr-x@   39 root  wheel   1.3K Jun 20 15:54 bin
drwxrwxr-t@    2 root  admin    68B Aug 16  2012 cores
dr-xr-xr-x     3 root  wheel   4.8K Jul  6 13:08 dev
lrwxr-xr-x@    1 root  wheel    11B Mar 27 12:09 etc -> private/etc
dr-xr-xr-x     2 root  wheel     1B Aug 12 21:41 home
-rw-r--r--@    1 root  wheel   7.8M May  1 20:57 mach_kernel
dr-xr-xr-x     2 root  wheel     1B Aug 12 21:41 net
drwxr-xr-x@    6 root  wheel   204B Mar 27 12:22 private
drwxr-xr-x@   68 root  wheel   2.3K Jun 20 15:54 sbin
lrwxr-xr-x@    1 root  wheel    11B Mar 27 12:09 tmp -> private/tmp
drwxr-xr-x@   13 root  wheel   442B Mar 29 23:32 usr
lrwxr-xr-x@    1 root  wheel    11B Mar 27 12:09 var -> private/var

ls나는 내가 할 수 있는 선택지가 셀 수 없이 많다는 것을 깨달았다.이 특별한 예의 경우그러나 이것은 일반적인 문제이며 특정 열을 쉽고 빠르게 얻을 수 있는 일반적인 솔루션을 원합니다.

cut정규식이 필요하지 않고 열이 단일 공백으로 구분되는 상황이 거의 발생하지 않으므로 잘라내지 않겠습니다. 작동한다면 완벽할 것입니다.

ls -hal / | cut -d'\s' -f5,9

awk그리고 sed내가 원하는 것보다 더 일반적입니다. 기본적으로 전체 언어 자체입니다. 나는 그들에게 반대할 생각이 없습니다. 단지 제가 최근에 그들과 많은 일을 하지 않은 이상, 그들의 방식으로 생각하고 유용한 글을 쓰기 시작하려면 상당한 정신적 변화가 필요하다는 것뿐입니다. 나는 보통 해결하려는 다른 문제에 대해 생각하고 있는데, 갑자기 하나 sed/ awk문제를 해결해야 하면 주의가 산만해집니다.

내가 원하는 것을 달성할 수 있는 유연한 지름길이 있습니까?

답변1

왜인지는 모르겠지만

ls -hal / | awk '{print $5, $9}'

귀하의 의견으로는 이것이 귀하의 사고 과정에 더 파괴적인 것보다

ls -hal / | cut -d'\s' -f5,9

효과가 있었다면 그랬을 것입니다. 꼭 적어야 하나요? 몇 줄만 awk자동으로 추가됩니다. {}(저에게 가장 어려운 문제는 어떤 필드 번호가 어떤 데이터에 해당하는지 기억하는 것입니다. 하지만 여러분에게는 그런 문제가 없을 수도 있습니다.)

당신은 사용할 필요가 없습니다모두awk의 기능: 단순히 특정 열을 출력하려면 awk에 대해 거의 알아야 합니다.

성가신 문제는 파일 이름과 함께 심볼릭 링크를 출력하려는 ​​경우 또는 파일 이름에 공백이 있을 수 있다는 것입니다. (또는 더 나쁘게는 개행 문자). 가정된 정규식 인식 클리핑을 사용하면 문제가 되지 않습니다(개행 제외) -f5,9. -f5,9-그러나 "필드 9에서 끝까지"에는 awk 구문이 없으므로 for 루프를 작성하는 방법을 기억해야 합니다. .

cut이것은 -style -f옵션을 awk 프로그램으로 변환한 다음 awk 프로그램을 실행하는 작은 쉘 스크립트입니다 . 더 나은 오류 검사가 필요하지만 작동하는 것 같습니다. (보너스: -d옵션은 awk 프로그램에 전달하여 처리됩니다.)

#!/bin/bash
prog=\{
while getopts f:d: opt; do
  case $opt in
    f) IFS=, read -ra fields <<<"$OPTARG"
       for field in "${fields[@]}"; do
         case $field in
           *-*) low=${field%-*}; high=${field#*-}
                if [[ -z $low  ]]; then low=1; fi
                if [[ -z $high ]]; then high=NF; fi
                ;;
            "") ;;
             *) low=$field; high=$field ;;
         esac
         if [[ $low == $high ]]; then
           prog+='printf "%s ", $'$low';'
         else
           prog+='for (i='$low';i<='$high';++i) printf "%s ", $i;'
         fi
       done
       prog+='printf "\n"}'
       ;;
    d) sep="-F$OPTARG";;
    *) exit 1;;
  esac
done
if [[ -n $sep ]]; then
  awk "$sep" "$prog"
else
  awk "$prog"
fi

빠른 테스트:

$ ls -hal / | ./cut.sh -f5,9-
7.0K bin 
5.0K boot 
4.2K dev 
9.0K etc 
1.0K home 
8.0K host 
33 initrd.img -> /boot/initrd.img-3.2.0-51-generic 
33 initrd.img.old -> /boot/initrd.img-3.2.0-49-generic 
...

답변2

나는 sed나 awk보다 더 간단한 해결책은 없다고 생각합니다. 하지만 자신만의 함수를 작성할 수 있습니다.

목록 기능은 다음과 같습니다(터미널에 복사하여 붙여넣기).

function list() { ls -hal $1 | awk '{printf "%-10s%-30s\n", $5, $9}'; }

그런 다음 목록 기능을 사용하십시오.

list /

list /etc

답변3

열이 무엇인지 설명하지 않고 "열"에 대해서만 이야기할 수는 없습니다!

Unix 텍스트 처리에서는 공백을 열(필드) 구분 기호로 사용하고 (자연) 개행 문자를 행 또는 레코드 구분 기호로 사용하는 것이 매우 일반적입니다. 다음 awk은 읽기 쉬운 훌륭한 도구입니다.

# for words (columns) 5 and 9:
ls -lah | awk '{print $5 " " $9}'
# or this, for the fifth and the last word:
ls -lah | awk '{print $5 " " $NF}'

열을 문자별로 정렬하면 더 좋을 것 같습니다 cut -c.

ls -lah | cut -c 31-33,46-

awk이 옵션을 사용하면 다른 필드 구분 기호를 사용할 수 있습니다 -F. 와 함께 -c(또는 -b)을 사용 하지 않는 경우 를 cut사용하여 -f출력할 열을 지정합니다.

비결은 입력을 이해하는 것입니다.

ls일반적으로 텍스트 처리 도구를 사용하여 , 및 유사한 도구의 출력을 구문 분석하는 것이 항상 좋은 생각은 아닙니다. 적어도 이식성/호환성을 원하는 경우에는 그렇지 않습니다 df. ps이러한 경우 POSIX 정의 형식으로 출력을 강제 실행해 보십시오. 때로는 -P출력을 생성하는 명령에 일부 옵션(아마도)을 전달하여 이를 달성할 수 있습니다. 때로는 환경 변수(예:)를 설정하거나 POSIXLY_CORRECT특정 바이너리(예: /usr/xpg4/bin/ls.

답변4

이에 대해 아무도 글을 쓰지 않은 것이 놀랍지만, cut반복되는 공백을 단일 구분 기호로 처리하지 않는다는 점이 유일한 반대라면, 반복되는 공백을 그냥 짜내는 것은 어떻습니까? 이것은 그 용도 중 하나입니다 tr.

ls -l | tr -s ' ' | cut -d ' ' -f5,9

귀하의 질문에 표시된 출력을 고려하면 ls -l결과는 다음과 같습니다.

1.2K .
1.2K ..
15K .DS_Store
272B .DocumentRevisions-V100
102B .MobileBackups
170B .Spotlight-V100
68B .Trashes
136B .bzvol
0B .dbfseventsd
0B .file
42K .fseventsd
68B .vol
9.6K Applications
238B Developer
2.3K Library
68B Network
136B System
204B Users
204B Volumes
1.3K bin
68B cores
4.8K dev
11B etc
1B home
7.8M mach_kernel
1B net
204B private
2.3K sbin
11B tmp
442B usr
11B var

관련 정보