목록을 특정 문자에 맞추는 방법?


13

텍스트 줄을 임의의 문자에 가로로 맞추는 데 사용할 수있는 명령 또는 명령 집합이 있습니까? 예를 들어, 전자 메일 주소 목록을 사용하면 모든 '@'문자가 세로로 정렬 된 텍스트 파일이 출력됩니다.

성공하기 위해서는 대부분의 줄의 시작 부분에 가변 수의 빈 공간을 추가해야한다고 생각합니다. 읽기에 더 많은 노력이 필요하기 때문에 별도의 열을 원하지 않습니다 (예 :) column -t -s "@" < file.txt.

전에:

123@example.com
456789@example.net
01234@something-else.com

후:

   123@example.com
456789@example.net
 01234@something-else.com

달리 말하면 : 문자를 앵커 포인트로 지정할 수 있습니까? 주변 텍스트가 가로로 가운데에 위치합니까? 이것에 대한 나의 유스 케이스는 시각적으로 쉽게 스캔 할 수 있도록 이메일 주소입니다.


1
여러 개의 @심볼 이 있으면 어떻게 됩니까?
Zeta

좋은 질문은 여러 개의 @기호가 전자 메일 주소와 관련해서는 안되지만 사용자는 한 줄에 한 문자의 인스턴스를 다른 텍스트가 중심을 둔 '앵커'로 선택할 수 있어야합니다.
Tom Brossman

1
@이메일 주소에는 여러 개의 기호가 허용됩니다 (예 :) tom"@brossmann"@example.com. 그래서 여러 @기호 가있는 경우 어떻게 해야하는지 묻습니다 . :).
Zeta

@Zeta @다양한 전자 메일 서비스에서 여러 기호를 사용할 수 없습니다. 필터링되지 않은 원시 사용자 입력을 처리하지 않는 한 "정상"이메일은 "실제"이메일보다 더 엄격한 표준에 맞는 "일반"이메일을 기대하는 것이 전적으로 합리적 @입니다.
Fund Monica의 소송

답변:


3

어 A 지 만 sedcolumn:

column -ts@ file.txt | sed -E 's/([^ ]+)([ ]+) (.+)/\2\1@\3/'

산출:

   123@example.com
456789@example.net
 01234@something-else.com

이제 생각합니다. 이것은 Sundeep 솔루션과 거의 동일하며 짧아 보이며 호출 횟수가 적 으며 각 라인에서 한 번만 발생 sed한다고 가정합니다 @.


1
더 짧을 수 있습니다 :column -ts@ input.txt | sed -r 's/([^ ]+)( *)\s\s/\2\1@/'
MiniMax

11

가장 간단한 방법으로 첫 번째 필드를 적절하게 큰 필드 너비로 인쇄 할 수 있습니다.

awk -F@ 'BEGIN{OFS=FS} {$1 = sprintf("%12s", $1)} 1' file
         123@example.com
      456789@example.net
       01234@something-else.com

AFAIK 특정 최대 필드 너비를 가정하지 않는 방법은 파일을 메모리에 보관하거나 두 번 통과해야합니다.


좋은 하나, 길이 하나를 얻을 수 있습니다 cw=$(cut -d@ -f1 file | wc -L)다음awk -v w="$cw" 'BEGIN{OFS=FS="@"} {$1 = sprintf("%*s", w, $1)} 1'
Sundeep

이것을 328 개의 주소 목록에 대해 테스트하면 10 개가 출력에서 ​​누락됩니다 (현재 318 줄). 명확성을 위해, 나는 달렸다 awk -F@ '{a[$1] = $2; w = length($1) > w? length($1) : w; next} END {for (i in a) printf("%*s%c%s\n", w, i, FS, a[i])}' INPUT-FILE.txt > OUT.txt. 나머지를 멋지게 형식화했지만 일부 데이터가 누락되었습니다.
Tom Brossman

1
@TomBrossman 덕분에 방금 심각한 결함이 있음을 깨달았습니다. 동일한 이름 필드를 처리하지 않습니다. 그 중 하나를 삭제
하겠습니다

같은 결과이지만 더 간결하게awk -F@ '{printf "%12s@%s\n", $1, $2}' input.txt
MiniMax

6

해키 솔루션, 입력 텍스트에 대해 많은 가정

$ # four commas to reduce chance of it affecting actual email address
$ sed 's/@/,,,,@/' ip.txt | column -t -s,,,,
123     @example.com
456789  @example.net
01234   @something-else.com

$ sed 's/@/,,,,@/' ip.txt | column -t -s,,,, | sed -E 's/^([^ ]+)( +)/\2\1/'
     123@example.com
  456789@example.net
   01234@something-else.com

4

구분 기호의 왼쪽에있는 모든 문자열을 오른쪽 정렬하는 가능한 가장 짧은 패딩 길이를 사용하는 빠른 Python 솔루션 :

#!/usr/bin/env python3
import sys
fieldsep = '@'
records = [line.rstrip('\n').split(fieldsep, 1) for line in sys.stdin]
col1_len = max((len(r[0]) for r in records), default=0)
for r in records:
    print(r[0].rjust(col1_len), r[1], sep=fieldsep)

용법:

python3 align-field.py < data.txt

2

또 다른 GNU awk+ column솔루션 :

awk '{ split($0,a,/ +/,sep); printf "%*s@%s\n",length($1 sep[1])-2,$1,$2 }' <(column -ts'@' file)

출력 :

   123@example.com
456789@example.net
 01234@something-else.com

이것이 어떻게 작동하는지 조금 더 추가해 주시겠습니까?
Joe

2

이것은 Bash 문자열 조작에서도 작동합니다.

배쉬 스크립트 (4.x) :

#!/bin/bash

read -d '' -r -a data <"data.txt"

for ((pos=0, i=0; i<${#data[@]}; i++)); do
    locl=${data[$i]%@*}                         # The local-part.
    [[ ${#locl} -gt $pos ]] && pos=${#locl}     # Determine the lengthiest $locl.
done

for ((i=0; i<${#data[@]}; i++)); do
    email=${data[$i]}
    locl=${email%@*}                            # The local-part.
    domain=${email#*@}                          # The email domain.
    printf '%*s@%s\n' $pos $locl $domain        # Align $locl to the right, at $pos.
done

결과:

   123@example.com
456789@example.net
 01234@something-else.com
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.