"열"의 출력이 ANSI 색상 입력과 일치하지 않는 이유는 무엇입니까?

"열"의 출력이 ANSI 색상 입력과 일치하지 않는 이유는 무엇입니까?

일부 데이터를 검색하기 위해 명령줄을 사용하고 있습니다(곱슬), 관련 필드 추출() 형식을 지정하고(기둥).

보기 흉하기는 하지만 잘 작동합니다(그러나 모든 스크립트는“길고 못생긴”한 줄) 그러나 특정 색상을 나열하려고 하면 잘못됩니다.

이것은 간단한(단순화된) 버전입니다.일하다:

curl "http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc" 2>/dev/null  \
 | awk 'BEGIN { FS= "|"; OFS= "|" }  {print  $1, $2, $5, $10, $11, $13}' \
 | column -t -s '|'

이제 일부 필드에 밑줄을 긋고 일부를 추가하고 싶습니다.ANSI 이스케이프 코드전혀:

curl "http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc" 2>/dev/null  \
 | awk 'BEGIN { FS= "|" ; OFS= "|" }  \
     $13~/Rieti/||/Perugia/ {$13="\033[1;31m"$13"\033[0m"} \
     $11~/[0-9]+/ && $11 > 5.8 {$11="\033[1;33m"$11"\033[0m"} 
     {print  $1, $2, $5, $10, $11, $13 }' \
 | column -t -s '|'

이제 정렬이 잘못되었습니다(그림 참조).

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

왜? 어떻게 해결할 수 있나요?

고쳐 쓰다

나는 이 질문을 본 적이 있다열 명령 및 색상 이스케이프 코드 관련 문제그러나 그의 대답은 풀 컬러 라인의 경우에 적용되므로 내 문제를 해결하지 못합니다.

내 경우에는 다음과 같은 이유로 답변을 적용하거나 조정할 수 없습니다(또는 할 수 없음).

  1. 문제는 후속 열에 관계없이 $11 열이 색칠된 경우로 제한됩니다.
  2. 색상 코드를 추가하는 좋은 방법이나 우아한 방법이 보이지 않습니다.뒤쪽에기둥.
    테스트를 위해 열의 출력을 awk로 보내는 경우 awk에 필드를 적절하게 분리하도록 지시하는 방법을 모르겠습니다(필드가 더 많은 공백으로 분리된 경우 정규식을 사용할 수 있지만 어떤 경우에는 분리가 단일 공백으로, awk 필드 구분 기호로 단어 사이의 공백과 공백을 인식하는 방법을 모릅니다.

내가 볼 수 있는 유일한 것은 재설정 색상 코드를 할당에서 인쇄 블록으로 이동하는 것입니다.첫 번째출력 전용 버전처럼 줄 간격이 더 좋습니다(아래 \033[0m두 번째 명령줄의 밑줄 참조). 여기에 이미지 설명을 입력하세요.

그럼 어떻게 해결하나요? 나처럼 색칠하는 더 우아한 방법이 또 있을까?

(알고 있습니다. Perl 라인을 사용하면 더 잘할 수 있지만 문제가 궁금합니다.)

답변1

이 문제를 해결하는 세 가지 간단한 방법이 있을 수 있습니다.

  1. 동일한 길이를 유지하려면 항상 이 열에 이스케이프 시퀀스를 사용하세요.
  2. 이스케이프 문자를 자체 열(추가 열 4개)에 넣으십시오. 단, 이렇게 하면 출력에 추가 공백이 추가됩니다.
  3. column제안한 대로 형식을 지정하세요.

다른 참고 사항은 여기에서 찾을 수 있습니다.ANSI 이스케이프 코드가 포함된 입력 데이터를 "표로 작성"하기 위한 쉘 도구.

첫 번째 옵션의 경우 \033[1;31mred 만 사용하는 대신 \033[31;1mred를 사용하고 \033[31;0m이전 코드, 심지어 동일한 시퀀스의 코드도 취소하는 "빨간색이 아닌" 또는 일반 - 0 코드를 사용하세요. 그러면 모든 열의 이스케이프 코드 길이가 동일해집니다.

BEGIN { FS=OFS="|" }  
function colour(ss,cc)    { return "\033[" cc ";1m" ss "\033[0m"; }
function notcolour(ss,cc) { return "\033[" cc ";0m" ss "\033[0m"; }
{  
  if ($13~/(RI|PG)/)    { $13=colour($13,31)    } 
                   else { $13=notcolour($13,31) }
  if (($11+0) > 5.8)    { $11=colour($11,33)    }
                   else { $11=notcolour($11,33) }
  print $1, $2, $5, $10, $11, $13 
}

(소스 데이터의 변경 사항과 일치하는 것을 포함하여 여러 가지 사소한 단순화 및 수정 사항도 위에 적용되었습니다.)

이 접근 방식의 문제점은 column합계 에 따라 달라진다는 것입니다 libc. (저는 util-linux-2.23.2에서 왔습니다.) 인쇄할 수 없는 콘텐츠가 발견되면 column실제 너비 대신 반환 코드가 -1이 됩니다. wcswidth()이는 실제로 테이블 형식을 엉망으로 만듭니다. util-linux-2.30.1의 최신 버전은 새로운 버전을 사용합니다.도서관문제를 해결하지만 인쇄할 수 없는 콘텐츠를 16진수로 인코딩된 버전으로 대체하여 그렇게 합니다. \x따라서 원본 이스케이프를 완전히 잃게 됩니다. // 우아하지 않은 방법으로 수정할 수 있습니다.

curl ... | awk ... | column -t -s '|' | while read -r line; do printf "$line\n"; done

printf탈출을 설명하는 곳 . 동일한 효과를 얻으 \033려면 자신의 코드로 바꿀 수 있습니다 . \\x1bLinux를 사용하시는지는 잘 모르겠습니다. )

세 번째 옵션의 경우 출력 구분 기호 column설정을 지원해야 하며 기본값은 공백 2개입니다. -o" "로 설정하면 |다음을 사용할 수 있습니다.

curl ... | column -t -s "|" -o "|" | awk '
BEGIN { FS="|" }  
function colour(ss,cc) { return sprintf("\033[%i;1m%s\033[0m",cc,ss) }
{  
  if ($13~/(RI|PG)/) { $13=colour($13,31) } 
  if (($11+0) > 5.8) { $11=colour($11,33) }
  print $1, $2, $5, $10, $11, $13 
}'

여기서의 비결은 column파이프로 구분된 입력을 사용한다는 것입니다.그리고출력하면 너비가 고정되고 awk모든 중요한 공간을 보존하면서 를 사용하여 안전하게 처리할 수 있습니다. column지원하지 않는 경우 -o다음을 사용하여 가짜로 만들 수 있습니다.

curl ... | sed -e 's/|/^|/g' | column -t -s^ | awk ...

이는 구분 기호를 " ^|"로 두 배로 늘리고, 를 column사용하고 ^, awkuses 를 사용합니다 |. 이로 인해 가설이 ^데이터에 확실히 존재하지 않게 됩니다. 하드 탭이 작동할 수 있습니다.

이제 "이유"를 아시리라 생각합니다. 하지만 명확하게 말씀드리면 다음과 같습니다.

  • columnstrlen()wcslen()/ 가 터미널에 표시된 길이와 일치하지 않는 옥텟(또는 문자)을 순진하게 계산할 수 있음
  • column길이를 계산하는 데 사용될 수 isprint()있으며 터미널 이스케이프에도 올바르지 않습니다.
  • column인쇄할 수 없는 콘텐츠가 발견되면 모든 열이 삭제될 수 있습니다(내 경우와 마찬가지로).

색상 코드 시퀀스를 제거하는 것은 상당히 간단한 문제이지만, column.

답변2

이 코드는 OP에서 수정되었습니다.

# Utility functions: print-as-echo, print-line-with-visual-space.
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }

pl " Results, highlight:"
# Original code from post:
# curl "http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc" 2>/dev/null  \
#  | awk 'BEGIN { FS= "|"; OFS= "|" }  {print  $1, $2, $5, $10, $11, $13}' \
#   | column -t -s '|'

# Codes my-highlight, my-hilite:
# https://unix.stackexchange.com/questions/46562/how-do-you-colorize-only-some-keywords-for-a-bash-script

SITE="http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc"

curl "$SITE" > data1

awk 'BEGIN { FS= "|"; OFS= "|" }  {print  $1, $5, $10, $11, $13}' data1 |
tee f1 |
column -t -s '|' |
my-highlight -r "Norcia"

pl " Results, hilite:"
awk 'BEGIN { FS= "|"; OFS= "|" }  {print  $1, $5, $10, $11, $13}' data1 |
tee f2 |
column -t -s '|' |
my-hilite -f blue "Norcia"

생산하다:

-----
 Results, highlight:
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   788    0   788    0     0   2566      0 --:--:-- --:--:-- --:--:--  2575
#EventID  Depth/Km  MagType  Magnitude  EventLocationName
7073641   8.1       Mw       6.0        1 km W Accumoli (RI)
7076161   8.0       Mw       5.3        5 km E Norcia (PG)
8663031   8.7       Mw       5.4        3 km SW Castelsantangelo sul Nera (MC)
8669321   7.5       Mw       5.9        3 km NW Castelsantangelo sul Nera (MC)
8788671   481.4     ML       5.8        Tirreno Meridionale (MARE)
8863681   9.2       Mw       6.5        5 km NE Norcia (PG)

-----
 Results, hilite:
#EventID  Depth/Km  MagType  Magnitude  EventLocationName
7073641   8.1       Mw       6.0        1 km W Accumoli (RI)
7076161   8.0       Mw       5.3        5 km E Norcia (PG)
8663031   8.7       Mw       5.4        3 km SW Castelsantangelo sul Nera (MC)
8669321   7.5       Mw       5.9        3 km NW Castelsantangelo sul Nera (MC)
8788671   481.4     ML       5.8        Tirreno Meridionale (MARE)
8863681   9.2       Mw       6.5        5 km NE Norcia (PG)

여기서는 mr.spuratic의 방법 3을 사용하여 색상을 지정합니다.뒤쪽에기둥화.

읽기 쉽도록 필드를 제거한 다음 2개의 스크립트를 적용했습니다(접두어로 이름 변경).내 거-여기) 스레드에서bash 스크립트의 특정 키워드만 색상을 지정하는 방법은 무엇입니까? -- 둘 다 문자열을 색칠하는 방식으로 작동합니다.노르시아컬럼을 실행한 후. (누가 내 게시물에 색상을 표시하는 방법을 알려주시면 감사하겠습니다.)

나는 이 문자열이 출력의 다른 곳에 나타나지 않는다고 가정하고 있으므로 특정 필드는 문제가 아니며 전체 줄이 일치하는지 확인합니다. 그렇지 않은 경우 이 솔루션은 스크립트에 주의를 환기시키는 것 외에는 거의 가치가 없습니다.힐라이트그리고강조하다.

이는 다음과 같은 시스템에서 수행되었습니다.

OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.9 (jessie) 
bash GNU bash 4.3.30

스크립트를 사용하는 경우강조하다, spc가 필요합니다(Debian 패키지에 있음).슈퍼 고양이); 관련 세부정보는 다음과 같습니다.

spc     colorize and print to standard output (man)
Path    : /usr/bin/spc
Package : supercat
Home    : http://supercat.nosredna.net/
Version : 2008
Type    : ELF64-bitLSBexecutable,x86-64,version1(SYSV ...)
Help    : probably available with -h,--help

행운을 빕니다... 건배, drl

답변3

이제 다들 설명하셨으니 column정렬되지 않은 출력이 표시되므로 다시 설명하지 않겠습니다.

대신 보여줄게또 다른 솔루션.

column유사한 출력을 얻는 데 관심이 있지만색상 코드그리고미국 국립표준협회이스케이프 시퀀스를 포함하는 버전을 만들었습니다.동일한 구문(지원되는 플래그의 경우) 로 column렌더링하고출력은 예상대로입니다.

온라인에서 다양한 솔루션을 찾았지만 모두 Bash루프에서 작동하므로 비교하면 매우 느립니다.Perl, 나는 사용했습니다.

스크립트를 찾을 수 있습니다여기.

./column_ansi.sh [--options]직접 실행 하거나( ) 소스에서 실행할 수 있습니다 ( source ./column_ansi.sh이 경우 명령은 다음과 같이 사용 가능함 column_ansi).

관련 정보