!["column -t"와 같은 명령은 출력에서 구분 기호를 유지합니다.](https://linux55.com/image/17322/%22column%20-t%22%EC%99%80%20%EA%B0%99%EC%9D%80%20%EB%AA%85%EB%A0%B9%EC%9D%80%20%EC%B6%9C%EB%A0%A5%EC%97%90%EC%84%9C%20%E2%80%8B%E2%80%8B%EA%B5%AC%EB%B6%84%20%EA%B8%B0%ED%98%B8%EB%A5%BC%20%EC%9C%A0%EC%A7%80%ED%95%A9%EB%8B%88%EB%8B%A4..png)
간단한 양식을 편집하고 있습니다. 포맷이 잘 되었으면 좋겠습니다. tbl
이나 이와 유사한 것을 사용할 수도 있지만 latex
이는 과도한 것처럼 보입니다. 일반 텍스트로도 충분합니다. 간단하기 때문에 소스를 출력으로 넣는 것이 좋을 것 같습니다. 따라서 소스도 보기 좋아야 합니다. 이것은 완벽한 작업을 수행해야 하는 것처럼 보입니다 column -s '|' -t
. 구분 기호를 찾고 각 열의 최대 너비에 따라 정렬할 공백을 자동으로 삽입합니다. 불행히도 추가 편집 후에는 다시 실행할 수 없도록 구분 기호가 제거됩니다. 출력이 입력 역할을 하도록 멱등적으로 이를 수행할 수 있는 좋은 텍스트 처리 도구가 있습니까? 아니면 제가 직접 작성해야 하나요?
편집: 다음은 내가 원하는 것의 예입니다.
foo | bar | baz
abc def | 12 | 23456
되어야 한다
foo | bar | baz
abc def | 12 | 3456
분리기 와 스페이서는 ' '
함께 사용하면 column -t
매우 효과적입니다 . 하지만 내 아이템에 공백이 있어서 사용할 수 없습니다. 스페이서를 디바이더와 다르게 만드는 것은 상황을 복잡하게 만듭니다. 구분 기호 옆의 구분 기호로 처리하는 것이 유용할 것이라고 생각했지만 그렇지 않습니다 column -s '|' -t
(분명히 현재 동작도 유용하지만).
답변1
귀하의 질문이 무엇인지 올바르게 이해했는지 잘 모르겠습니다. 하지만 추가 시간 구분 기호를 추가하면 이 문제가 해결됩니까? 따라서 두 번째 구분 기호를 사용하여 구분 기호를 표시하고 원래 구분 기호는 변경되지 않은 상태로 유지할 수 있습니다.
각 "|"에 "@"를 추가하여 열 명령에 대한 입력이 "xxx @| yyyy"가 되는 이 예를 참조하세요. 열은 "@"을 처리하고 "|"는 영향을 받지 않습니다.
~$ echo "foo | this is some text | bar" | sed 's/|/@|/g' | column -s '@' -t
foo | this is some text | bar
답변2
문의하신 시점에는 이 기능을 사용할 수 없었으나,섹션 2.23 기준 column
from을 util-linux
사용하면 출력 구분 기호를 선택할 수 있습니다.
-o, --output-separator string
Specify the columns delimiter for table output (default is two spaces).
그러니 그냥 실행하세요:
column -s '|' -o '|' -t infile
답변3
이것은 bash 스크립트입니다. "column -t"를 사용하지 않으며 구분 기호는 IFS(또는 적어도 awk의 IFS 빌드)이기 때문에 IFS와 정확히 동일하게 처리됩니다. 기본 구분 기호는 $' \t'입니다.
스크립트는 가장 오른쪽 필드를 완전히 채웁니다.
"열"은 이를 수행하지 않습니다. 이 스크립트는
모든 열을 채워 테이블 프레임을 생성하도록 쉽게 수정될 수 있습니다 .
노트. 입력 파일은 두 번 처리되어야 합니다
("열"도 이 작업을 수행해야 함).
첫 번째 단계는 열 최대 너비를 가져오는 것입니다.
두 번째 패스는 확장 필드(각 열)입니다.
몇 가지 옵션을 추가했습니다.명백한 버그를 수정했습니다(변수 이름 바꾸기 :(
- -l 들여쓰기된 필드 왼쪽의 공백을 자릅니다.
- -r 가장 넓은 텍스트보다 넓은 공백을 오른쪽으로 자릅니다(열의 경우).
- -b -l 및 -r
- -L 왼쪽 출력 구분 기호 추가
- -R 오른쪽 출력 구분 기호를 추가합니다.
- -B -L 및 -R
- -S 출력 구분 기호를 선택합니다.
#!/bin/bash
#
# script [-F sep] [file]
#
# If file is not specified, stdin is read
#
# ARGS ######################################################################
l=;r=;L=;R=;O=;F=' ' # defaults
for ((i=1;i<=${#@};i++)) ;do
case "$1" in
-- ) shift 1;((i--));break ;;
-l ) l="-l";shift 1;((i-=1)) ;; # left strip whitespace
-r ) r="-r";shift 1;((i-=1)) ;; # right strip whitespace
-b ) l="-l";r="-r";shift 1;((i-=1)) ;; # strip both -l and -r whitespace
-L ) L="-L";shift 1;((i-=1)) ;; # Left output delimiter is added
-R ) R="-R";shift 1;((i-=1)) ;; # Right output delimiter is added
-B ) L="-L";R="-R";shift 1;((i-=1)) ;; # output Both -L and -R delimiters
-F ) F="$2";shift 2;((i-=2)) ;; # source separator
-O ) O="$2";shift 2;((i-=2)) ;; # output separator. Default = 1st char of -F
-* ) echo "ERROR: invalid option: $1" 1>&2; exit 1 ;;
* ) break ;;
esac
done
#
if [[ -z "$1" ]] ;then # no filename, so read stdin
f="$(mktemp)"
ifs="$IFS"; IFS=$'\n'; set -f # Disable pathname expansion (globbing)
while read -r line; do
printf "%s\n" "$line" >>"$f"
done
IFS="$ifs"; set +f # re-enable pathname expansion (globbing)
else
f="$1"
fi
[[ -f "$f" ]] || { echo "ERROR: Input file NOT found:" ;echo "$f" ;exit 2 ; }
[[ -z "$F" ]] && F=' ' # input Field Separator string
[[ -z "$O" ]] && O="$F" # output Field Separator
O="${O:0:1}" # use single char only
# MAIN ######################################################################
max="$( # get max length of each field/column, and output them
awk -vl="$l" -vr="$r" -vL="$L" -vR="$R" -vF="$F" -vO="$O" '
BEGIN { if (F!="") FS=F }
{ for (i=1;i<=NF;i++) {
if (l=="-l") { sub("^[ \t]*","",$i) }
if (r=="-r") { sub("[ \t]*$","",$i) }
len=length($i); if (len>max[i]) { max[i]=len }
if (i>imax) { imax=i }
}
}
END { for(i=1;i<=imax;i++) { printf("%s ",max[i]) } }
' "$f"
)"
awk -vl="$l" -vr="$r" -vL="$L" -vR="$R" -vF="$F" -vO="$O" -v_max="$max" '
BEGIN { if (F!="") FS=F; cols=split(_max,max," ") }
{ # Bring each field up to max len and output with delimiter
printf("%s",L=="-L"?O:"")
for(i=1;i<=cols;i++) { if (l=="-l") { sub("^[ \t]*","",$i) }
if (r=="-r") { sub("[ \t]*$","",$i) }
printf("%s%"(max[i]-length($i))"s%s",$i,"",i==cols?"":O)
}
printf("%s\n",R=="-R"?O:"")
}
' "$f"
# END #######################################################################
if [[ -z "$1" ]] ;then # no filename, so stdin was used
rm "$f" # delete temp file
fi
exit
답변4
이는 2단계 조정입니다.헤르몬톨리우답변, 입력 데이터에서 구분 기호를 추측하여 하드 코딩할 필요가 없습니다.
- 공백으로 묶인 영숫자가 아닌 단일 문자에 대한 입력을 구문 분석하고 가장 일반적인 문자로 정렬하며 가장 일반적인 문자가 할당된 구분 기호라고 가정합니다
$d
. - 다소 진행헤르모놀리우답은 있지만 ASCII를 사용하는 것입니다.유효하지 않은
@
다음 대신 패딩으로피터 오의 의견.
코드는 파일 이름이나 입력을 받아들이는 함수입니다.표준 입력:
algn() {
d="$(grep -ow '[^[:alnum:]]' "${1:-/dev/stdin}" | \
sort | uniq -c | sort -rn | sed -n '1s/.*\(.$\)/\1/p')" ;
sed "s/ *$d */\x01$d /g" "${1:-/dev/stdin}" | column -s $'\001' -t ;
}
출력 algn foo
(또는 algn < foo
):
foo | bar | baz
abc def | 12 | 23456