선을 분할하고 다시 정렬

선을 분할하고 다시 정렬

세미콜론으로 구분된 130개의 필드가 포함된 파일이 있습니다. 어떻게든 재배열하고 싶어요.

다음 예를 고려하십시오.

문서샘플.txt:

1;2;3;4;8;5;6;7;9;10;11;
11;12;13;14;18;15;16;17;19;20;21;

원하는 출력(파일요청작업.txt):

1;2;3;4;5;6;7;8;9;10;11;
11;12;13;14;15;16;17;18;19;20;21;

여덟 번째 요소의 위치가 잘못되었습니다. 내가 한 일은 프로세스를 단순화하는 것뿐이었습니다. 문제는 121개의 필드가 있으므로 깔끔한 AWK 명령을 사용하여 전체 파일에 대해 한 줄의 텍스트를 조작할 수 없다는 것입니다.

나는 다음을 시도했고 작동합니다. 더 효율적이고 읽기 쉬운 솔루션을 제안해 주실 수 있나요? 귀하의 솔루션에 대한 설명도 요청합니다.

각 필드에는 등을 포함하는 공백/문자열로 구분된 숫자와 문자열이 포함될 수 있습니다 $.#

#!/bin/bash

file="sample.txt"

while read -r line
do

    array=($(echo "$line" | sed 's/;/ /g'))

    printf -v first '%s;' "${array[@]:0:4}"
    printf -v last '%s;' "${array[@]:8:12}"
    printf -v second '%s;' "${array[@]:5:3}"
    printf -v third '%s;' "${array[@]:4:1}"

    echo "${first}${second}${third}${last}" >> req_op.txt

done < $file

실제 필드 수:

입력하다:

1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|143|138|139|140|141|142|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162

산출:

1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162

@Quasímodo가 공유한 sed 명령을 수정했습니다. 이제 예상대로 작동합니다.

sed -E 's~(([^\|]*\|){137})([^\|]*\|)(([^\|]*\|){5})~\1\4\3~' sample.txt

답변1

펄 사용:

$ perl -F';' -lne 'splice @F, 7, 0, (splice @F, 4, 1); print join ";", @F' sample.txt 
1;2;3;4;5;6;7;8;9;10;11
11;12;13;14;15;16;17;18;19;20;21

예시 보기Perl에서 슬라이스 및 다이싱된 배열 연결

답변2

awk를 사용하세요

awk 'BEGIN{FS=OFS=";"}{$8=$8 FS $5;$5=RS;sub(RS FS,"");print}' sample.txt > req_op.txt

설명이 포함된 확장 버전:

awk '
  BEGIN{FS=OFS=";"} #Sets input (FS) and output (OFS) field separators
  {                 #For each line
    $8=$8 FS $5     #Append the 5th field after the 8th field
    $5=RS           #Put a newline (the record separator) in the 5th field
    sub(RS FS,"")   #Remove the newline and its following FS
    print           #Print the resulting line
  }     
' sample.txt > req_op.txt

다섯 번째 필드를 일시적으로 대체하기 위해 레코드 구분 기호(귀하의 경우 개행)를 선택한 이유는 무엇입니까? 확실히 기록에 남지 않는 유일한 캐릭터이기 때문입니다. 그런 다음 sub(RS FS,"")어딘가에 빈 필드가 있더라도 5번째 필드를 반드시 삭제하세요.

해당 줄을 이해하지 못하는 경우 sub해당 줄을 제거하고 출력에 어떤 일이 발생하는지 확인하세요.

Sed 사용

  • 확장된 정규식을 사용하십시오:

    sed -E 's|(([^;]*;){4})([^;]*;)(([^;]*;){3})|\1\4\3|' sample.txt > req_op.txt
    
  • POSIX를 준수하는 기본 정규식을 사용하면 기본적으로 위와 동일하지만 각각 (){}이스케이프가 필요합니다(한숨!).

    sed 's|\(\([^;]*;\)\{4\}\)\([^;]*;\)\(\([^;]*;\)\{3\}\)|\1\4\3|' sample.txt > req_op.txt
    

ssed의 대체 명령입니다. 그 뒤의 문자는 구분 기호입니다(내가 선택한 것 |). 정규식 슬롯, 대체 슬롯 및 플래그 슬롯(이 경우 비어 있음)을 정의합니다.

정규식의 일부 요소는 다음과 같습니다.

  • [^;]*;: 세미콜론 이외의 문자가 0개 이상 나타나고 그 뒤에 세미콜론이 옵니다.
  • ([^;]*;){4}: 위의 표현은 캡처링 그룹에 속하며 정확히 4번 반복되어야 합니다.
  • (([^;]*;){4})\1: 위 표현식은 외부 캡처 그룹에 있으며 대체 표현식에서 재현됩니다. 내부 캡처 그룹이 대체됩니다 \2.

따라서 첫 번째 줄에서 일어나는 일은 1;2;3;4;8;5;6;7;9;10;11;다음과 같습니다.

  • \1얻다1;2;3;4;
  • \3얻다8;
  • \4얻다5;6;7;

로 재정렬됩니다 \1\4\3.

역참조에 대한 자세한 내용은 다음을 참조하세요.패턴의 일부를 보존하려면 \1을 사용하세요. (그런데 이 페이지는 좋은 sed 튜토리얼입니다.)

답변3

를 사용하면 perl다음 작업도 수행할 수 있습니다.

perl -F';' -lape '$_ = join ";", @F[0..3,5..7,4,8..10]' sample

아니면 당신을 위해실제입력하다:

perl -F'[|]' -lape '$_ = join "|", @F[0..136,138..142,137,143..161]' input

답변4

파이썬

#!/usr/bin/python
k=open('filename','r')
r=[]
v=[]
for i in k:
    r=[]
    v=[]
    j=i.strip().split(";")
    for g in j:
        if (g != ''):
            r.append(int(g.strip()))
    r.sort()
    e=r
    for d in e:
        v.append(str(d))
        v.append(str(";"))
    print "".join(v)

산출

1;2;3;4;5;6;7;8;9;10;11;
11;12;13;14;15;16;17;18;19;20;21;

관련 정보