CSV 파일 내에서 1~9 사이의 한 자리를 두 자리로 변환

CSV 파일 내에서 1~9 사이의 한 자리를 두 자리로 변환

이와 같은 수천 개의 행이 포함된 CSV 파일이 있습니다.

1664;4;5;35;37;43;5;6
1663;21;23;32;40;49;8;11
1662;16;17;34;35;44;5;10
1661;2;9;23;32;40;6;7
1660;23;25;30;44;47;9;12
1659;3;5;9;32;43;6;10
1658;4;6;10;13;34;3;5
1657;8;9;33;35;40;3;6
1656;15;20;31;44;48;1;3
1655;25;27;35;40;45;7;11
1654;7;32;33;34;38;6;9
1653;5;7;11;27;37;6;12
1652;7;31;33;35;36;7;10
1651;4;12;34;35;45;1;9
1650;5;8;29;35;48;5;6
1649;2;11;28;42;48;4;9
1648;2;11;12;19;38;4;8

1부터 9까지의 숫자는 모두 한 자리 숫자임을 알 수 있습니다.

sed이 숫자 앞에 0을 추가하여 이 숫자를 어떻게 사용하거나 두 자리로 변환할 수 있습니까 ?

01 02 03 04 05 06 07 08 09

바꾸다

1 2 3 4 5 6 7 8 9

미리 감사드립니다.

답변1

다음을 사용하는 솔루션은 다음과 같습니다 awk.

awk 'BEGIN{FS=OFS=";"} {for (i=1;i<=NF;i++) $i=sprintf("%02d",$i)} 1' file.csv

그러면 먼저 입력 및 출력 필드 구분 기호가 로 설정됩니다 ;. 그런 다음 모든 필드를 반복하고 다음을 사용합니다 sprintf()(여기서효과적으로필드 내용이 이미 두 자리 숫자인 경우에는 변경되지 않습니다.

1액션 블록 외부에 있는 것처럼 보이는 것은 awk모든 변경 사항을 포함하여 현재 줄을 인쇄하도록 지시합니다.

기본적 으로 awk파일은 수정되지 않고 로만 인쇄되므로 stdout다음을 수행할 수 있습니다.

  • 출력을 임시 파일로 리디렉션하고 다음과 같이 이름을 바꿔야 합니다.
    awk ' ... ' file.csv > output.csv && mv output.csv file.csv
    
  • 또는 확장 기능을 awk지원하는 버전을 사용하세요 -i inplace.
    awk -i inplace ' ... ' file.csv
    

또한 이 특별한 사례는 한 자리 또는 두 자리 숫자만 포함하는 입력 예를 기반으로 사용자 정의되었습니다. n패딩 숫자의 보다 일반적인 경우에는 다음을 사용할 수 있습니다 .

awk -v n=3 'BEGIN{FS=OFS=";"} {for (i=1;i<=NF;i++) $i=sprintf("%0*d",n,$i)} 1' file.csv

답변2

이를 사용하여 sed단일 숫자 "단어"를 선택하고 앞에 0을 붙일 수 있습니다.

sed -E 's/\<([0-9])\>/0\1/g' {file}

포괄적인:

  • -E플래그는 sed표준/일반 정규식 대신 ERE(확장 정규식)가 사용되도록 보장합니다.
  • s/ …pattern… / …replacement… /g…pattern…해당 대체 항목 에 ERE 일치 항목을 적용하는 대체 항목을 정의합니다 …replacement…. ("전역") 플래그 로 인해 g일치/바꾸기가 한 줄에 최대한 많이 적용됩니다.
  • 행 선택이 없으므로 이 규칙은 입력의 모든 행에 암시적으로 적용됩니다.

ERE 일치 패턴에서:

  • \<\>단어 경계를 나타냅니다 .
  • ()나중에 재사용할 수 있는 그룹화 표현식을 식별합니다 .
  • [0-9]임의의 숫자입니다

ERE 교체에서:

  • 00문자 그대로의 문자 입니다
  • \1첫 번째 그룹화 표현식으로 캡처된 텍스트(예: 단일 숫자의 인스턴스)를 삽입합니다.

산출:

1664;04;05;35;37;43;05;06
1663;21;23;32;40;49;08;11
1662;16;17;34;35;44;05;10
1661;02;09;23;32;40;06;07
1660;23;25;30;44;47;09;12
1659;03;05;09;32;43;06;10
1658;04;06;10;13;34;03;05
1657;08;09;33;35;40;03;06
1656;15;20;31;44;48;01;03
1655;25;27;35;40;45;07;11
1654;07;32;33;34;38;06;09
1653;05;07;11;27;37;06;12
1652;07;31;33;35;36;07;10
1651;04;12;34;35;45;01;09
1650;05;08;29;35;48;05;06
1649;02;11;28;42;48;04;09
1648;02;11;12;19;38;04;08

,이 경우 ;파일이 실제로 CSV(쉼표로 구분된 필드)인지, 세미콜론(" ")으로 구분된 필드가 있는지 또는 공백으로 구분된 필드가 있는지는 중요하지 않습니다.

sed지원하는 경우 "현재 위치"에서 파일을 편집할 수 있지만 -i, 대부분의 다른 유틸리티와 마찬가지로 "현재 위치" 효과는 실제로 "임시 파일에 쓴 다음 원본 파일로 대체"하여 뒤에서 달성된다는 점에 유의하세요. 파일 "임시":

sed -E 's/\<([0-9])\>/0\1/g' file >file.$$.tmp &&
    mv -f file.$$.tmp file
rm -f file.$$.tmp

답변3

사용밀러유형 추론( -A)을 사용하고 패딩이 0이고 최소 필드 너비가 2인 정수 값을 출력합니다.

mlr -A --nidx --fs ';' --ofmt '%02d' cat file

귀하의 입력 예를 기반으로 데이터가 실제로 CSV가 아닌 색인 번호로 매겨져 있다고 가정합니다.

답변4

사용행복하다(이전 Perl_6)

~$ raku -MText::CSV -e 'my @a = csv(in => $*IN, sep => ";", strict => True);        \
                        @a = @a>>.map( {sprintf "%.2d", $_ } );    \
                        csv(in => @a, out => $*OUT, sep => ";");'  file 

위의 코드는 Raku의 Text::CSV모듈을 사용합니다. 첫 번째 명령문에서는 CSV 파일을 읽고 열 구분 기호로 세미콜론을 sep허용하도록 매개변수를 설정합니다 . ;두 번째 명령문에서는 sprintf명령이 "%.2d"각 열의 최소 너비를 2로 설정하고 0으로 채웁니다. 출력에서 ;세미콜론은 열 구분 기호로 되돌아갑니다. 그렇지 않으면 기본값(쉼표)이 사용됩니다.

위의 답변은 각 열이 정수인 CSV 파일에 적용됩니다. 지금까지서명되지 않은정수 NYI(아직 구현되지 않음) 사용하기 가장 좋습니다form 에서 공백 대신 0으로 채우기를 나타내는 형식 지정 코드에 sprintf추가된 사항에 유의하세요 . 0아래의 두 번째 대체 설명:

@a = @a>>.map( {sprintf "%02s", $_ } );

입력 예:

1664;4;5;35;37;43;5;6
1663;21;23;32;40;49;8;11
1662;16;17;34;35;44;5;10
1661;2;9;23;32;40;6;7
1660;23;25;30;44;47;9;12
1659;3;5;9;32;43;6;10
1658;4;6;10;13;34;3;5
1657;8;9;33;35;40;3;6
1656;15;20;31;44;48;1;3
1655;25;27;35;40;45;7;11
1654;7;32;33;34;38;6;9
1653;5;7;11;27;37;6;12
1652;7;31;33;35;36;7;10
1651;4;12;34;35;45;1;9
1650;5;8;29;35;48;5;6
1649;2;11;28;42;48;4;9
1648;2;11;12;19;38;4;8

출력 예(위 예):

1664;04;05;35;37;43;05;06
1663;21;23;32;40;49;08;11
1662;16;17;34;35;44;05;10
1661;02;09;23;32;40;06;07
1660;23;25;30;44;47;09;12
1659;03;05;09;32;43;06;10
1658;04;06;10;13;34;03;05
1657;08;09;33;35;40;03;06
1656;15;20;31;44;48;01;03
1655;25;27;35;40;45;07;11
1654;07;32;33;34;38;06;09
1653;05;07;11;27;37;06;12
1652;07;31;33;35;36;07;10
1651;04;12;34;35;45;01;09
1650;05;08;29;35;48;05;06
1649;02;11;28;42;48;04;09
1648;02;11;12;19;38;04;08

입력/출력: 출력을 새 파일로 리디렉션하여 @AdminBee 또는 @roiama(또는 둘 다)로부터 훌륭한 코드를 얻을 수 있습니다. 직접 입출력을 원하는 경우코드 내에서자체 $*IN이며 $*OUT동적 값은 PATH로 대체될 수 있습니다(자세한 내용은 아래 두 번째 URL 참조).

https://docs.raku.org/routine/sprintf
https://github.com/Tux/CSV
https://raku.org

관련 정보