tsv/csv의 큰 열 사이에서 문자를 자르는 방법은 무엇입니까?

tsv/csv의 큰 열 사이에서 문자를 자르는 방법은 무엇입니까?

CSV 파일이 있습니다.

1,abcde aa aaaa aaa aaaa abcde,4
2,efghi ooo oooo ooo oooo efghi,5

첫 번째와 마지막 5자로 두 번째 열을 자르고 3개의 점으로 채우려면 이 열이 필요합니다. 이 목표를 달성하는 방법은 무엇입니까?

1,abcde ... abcde,4
2,efghi ... efghi,5

답변1

해결책 sed

sed -E 's/(.*,.{5}).*(.{5},.*)/\1...\2/'

두 번째 "열"(필드)이 9자 이하이면 입력이 변경되지 않은 채로 유지되지만 정확히 10자라도 " "가 삽입됩니다(어떤 문자도 대체하지 않더라도).

     입력하다                       산출
9,abcdefghi,z 9,abcdefghi,z
(잔돈은 그대로 유지해주세요)
10,abcdefghij,z 10,abcde...fghij,z
(참고로 이건더 길게입력보다. )

캐스의 대답두 번째 필드가 대체할 가치가 있을 만큼 충분히 긴지 명시적으로 확인하는 것이 좋습니다. 내 대답은 질문을하는 것이기 때문에설명하다(점 3개 삽입) 표시되는 것(공백 + 점 3개 + 공백 삽입 또는 입력에 공백 남기기) 대신 처음 5개와 마지막 5개 사이에 4개 이상의 다른 문자가 있는 경우 혜택을 받습니다. 이 문제를 처리하려면 다음 명령을 사용할 수 있습니다.

sed -E 's/(.*,.{5}).{4,}(.{5},.*)/\1...\2/'
     입력하다                     산출
10,abcdefghij,z 10,abcdefghij,z
(잔돈은 그대로 유지해주세요)
13,abcdefghijklm,z 13,abcdefghijklm,z
(여전히 변화가 없음)
14,abcdefghijklmn,z 14,abcde...jklmn,z
(입력한 문자보다 한 글자 더 짧습니다.)
20,abcdefghijklmnopqrst,z 20,abcde...pqrst,z

.{4,}4개 이상의 문자를 일치시킵니다. 물론 음수가 아닌 정수 4로 변경할 . 예를 들어 반복되는 cas에 대해 제안된 답변을 사용하려면 를 min=20사용합니다  .{11,}.

답변2

$2가 잘라내려는 길이(15자: 5자 + 공백 + 3점 + 공백 + 5자)보다 길지 않으면 수행할 가치가 없습니다.

$ awk -F, '
  BEGIN {OFS=FS; min=15};
  length($2) > min { $2 = substr($2,1,5)  " ... " substr($2, length($2)-4) }1' input.csv 
1,abcde ... abcde,4
2,efghi ... efghi,5
3,short field,5

$ cat input.csv 
1,abcde aa aaaa aaa aaaa abcde,4
2,efghi ooo oooo ooo oooo efghi,5
3,short field,5

또는 length($2)각 입력 행에 대해 한 번만 계산합니다. (OFS 및 최소값을 설정하는 다른 방법도 표시됩니다.)

awk -F, -v OFS=, -v min=15 '
  { L=length($2) };
  L > min { $2 = substr($2,1,5)  " ... " substr($2, L-4) }1' input.csv

1 그보다 훨씬 길지 않으면 수행할 가치가 없을 것입니다. 따라서 최소 20자 정도일 것입니다.

답변3

현재 예에서 필요한 것은 다음과 같습니다.

$ sed 's/ .* / ... /' file
1,abcde ... abcde,4
2,efghi ... efghi,5

또는 실제로 두 번째 필드에서만 작업해야 하는 경우 다음을 수행하세요.

$ awk 'BEGIN{FS=OFS=","} {sub(/ .* /," ... ",$2)}1' file
1,abcde ... abcde,4
2,efghi ... efghi,5

이것이 필요한 전부가 아니라면 질문을 편집하여 적용되지 않는 경우를 포함하여 더욱 대표적인 입력/출력 예제를 표시하십시오.

답변4

사용행복하다(이전 Perl_6)

raku -pe 's/ \, <( (<alnum>**5) .* (<alnum>**5) )> \, /$0 ... $1/;' 

또는

raku -pe 's/ \, <( $<head>=[<alnum>**5] .* $<tail>=[<alnum>**5] )> \, /$<head> ... $<tail>/;' 

입력 예:

1,abcde aa aaaa aaa aaaa abcde,4
2,efghi ooo oooo ooo oooo efghi,5

출력 예(위의 두 코드 예):

1,abcde ... abcde,4
2,efghi ... efghi,5

위의 답변은행복하다프로그래밍 언어는 Perl 프로그래밍 언어 계열에 속합니다. 위의 두 답변은 기본적으로 column_1의 쉼표 오른쪽에 있는 처음 5자가 <alnum>(문자 + 밑줄 + <digits>)라는 가정을 기반으로 합니다. 더 넓은 범위의 문자를 처리하는 방법에 대한 자세한 내용은 아래 코드를 참조하세요.

Raku는 더욱 강력하고 읽기 쉽도록 설계된 새로운 정규식 엔진을 사용합니다. 첫 번째 예에서는 번호가 매겨진 캡처( $0, $1)가 사용되는 반면, 두 번째 예에서는 캡처( $<head>, $<tail>)가 사용됩니다. 위 코드의 하이라이트에는 1) 숫자가 아닌 문자를 현명하게 이스케이프 처리 \,(추측할 필요가 없음), [ … ]정규식 "원자"를 대괄호로 그룹화, ( … )대괄호로 캡처, 처음부터 번호 매기기 캡처 , 일반 수량 $0자로 사용 ( **min..max예: **5), 캡처 마커를 사용하여 일치 개체 외부의 텍스트를 묘사합니다 <( … )>. 그러면 쉼표(일치 개체 외부)가 실수로 제거되지 않습니다.

위의 답변은 (문자, 밑줄) + 로 구성된 Raku의 내장 <alnum>문자 클래스를 사용합니다 . 그러나 더 다양한 문자를 잘라낼 수도 있습니다. 내장 문자 클래스를 사용자 정의(사용자 정의 및/또는 열거형) 문자 클래스로 교체해 볼 수 있습니다 . 사용자 정의 문자 클래스는 공백이 아닌 문자(예: 숫자의 소수점)에서 쉼표를 빼고 마이너스 쉼표를 사용 합니다 .<alpha><digits><alnum><+[\S]-[,]><+[\S]-[,]>+[\S]-[,]

아래에는 합리적인 결과가 나와 있습니다. 예를 들어 1행과 2행은 적절하게 단축된 반면 line_3/column_2(쉼표가 아닌 문자 4개만 길이)는 너무 짧아서 더 이상 잘릴 수 없습니다. (“단거리 필드” 영감을 주신 @cas에게 감사드립니다):

raku -pe 's/ \, <(( <+[\S]-[,]>**5) .* ( <+[\S]-[,]>**5 ))> \, /$0 ... $1/;'  

입력 예:

1,$2.37 aa aaaa aaa aaaa abcde,1_end
2,##IN: ooo oooo ooo oooo efghi,2_end
3,#OUT, ooo oooo ooo oooo efghi,3_end
4,short field,4_end
5,thin ice,5_end

예제 출력:

1,$2.37 ... abcde,1_end
2,##IN: ... efghi,2_end
3,#OUT, ooo oooo ooo oooo efghi,3_end
4,short ... field,4_end
5,thin ice,5_end

https://raku.org

관련 정보