각 블록의 필드에서 길이가 다른 데이터 블록을 정렬하는 방법

각 블록의 필드에서 길이가 다른 데이터 블록을 정렬하는 방법

<및 로 표시되는 다양한 행 수의 데이터 덩어리가 포함된 RDF 파일이 있습니다 />. 각 블록 내에는 로 식별되는 필드가 있습니다 name="some name". name각 블록의 행 순서를 변경하지 않고 값을 기준으로 블록을 정렬해야 합니다 . 또한 각 블록에는 숫자가 있는 필드가 있습니다. 이 필드의 번호를 다시 매겨야 합니다.1도착하다N각 블록의 정렬 위치를 기준으로 합니다.

다음은 3개 블록의 예입니다.

<RDF:Description RDF:about="rdf:#$CHROME1"
 NS1:name="AAA Carolinas"
  NS1:urlToUse=""
  NS1:whereLeetLB="off"
  NS1:leetLevelLB="1"
  NS1:hashAlgorithmLB="md5"
  NS1:passwordLength="16"
  NS1:usernameTB="user"
  NS1:counter=""
  NS1:charset="a9b0c8d1e7f2g6h3i5j4klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV123456789"
  NS1:prefix="6%Fl"
  NS1:suffix="I$5g"
  NS1:protocolCB="false"
  NS1:subdomainCB="true"
  NS1:domainCB="true"
  NS1:pathCB="false"
  />
<RDF:Description RDF:about="rdf:#$CHROME2"
 NS1:name="Adobe Forums"
  NS1:urlToUse="adobeforums.com"
  NS1:whereLeetLB="off"
  NS1:leetLevelLB="1"
  NS1:hashAlgorithmLB="md5"
  NS1:passwordLength="12"
  NS1:usernameTB="username"
  NS1:counter=""
  NS1:charset="a9b0c8d1e7f2g6h3i5j4klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV"
  NS1:prefix=""
  NS1:suffix=""
  NS1:protocolCB="false"
  NS1:subdomainCB="true"
  NS1:domainCB="true"
  NS1:pathCB="false"
  NS1:pattern0="*adobeforums.com*"
  NS1:patternenabled0="true"
  NS1:patterndesc0=""
  NS1:patterntype0="wildcard"
  />
<RDF:Description RDF:about="rdf:#$CHROME3"
 NS1:name="Adorama"
  NS1:urlToUse="adorama.com"
  NS1:whereLeetLB="off"
  NS1:leetLevelLB="1"
  NS1:hashAlgorithmLB="md5"
  NS1:passwordLength="8"
  NS1:usernameTB="username"
  NS1:counter=""
  NS1:charset="a9b0c8d1e7f2g6h3i5j4klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV"
  NS1:prefix=""
  NS1:suffix=""
  NS1:protocolCB="false"
  NS1:subdomainCB="false"
  NS1:domainCB="true"
  NS1:pathCB="false"
  NS1:pattern0="*adorama.com*"
  NS1:patternenabled0="true"
  NS1:patterndesc0=""
  NS1:patterntype0="wildcard"
  NS1:pattern1="www.adoramapix.com*"
  NS1:patternenabled1="true"
  NS1:patterndesc1=""
  NS1:patterntype1="wildcard"
  />

제가 언급한 숫자는 $CHROME위 예시의 숫자입니다. 저는 오래된 어셈블리, COBOL, Fortran, Basic 프로그래머이지만 스크립팅이나 최신 언어에는 익숙하지 않습니다. 아마도 Basic 프로그램에서 이 작업을 수행할 수 있지만 가능하다면 Linux 솔루션을 원합니다.

답변1

어떤 캐릭터가 있었으면 좋겠습니다. 또는 적어도 일부는 있었으면 좋겠습니다.- 귀하의 파일에는 절대 나타나지 않습니다. 나는 이것이 에 해당한다고 가정합니다 |. 더 안전하려면 ||.

다음 명령을 실행하세요:

sed -n -e H -e '/^ *\/> *$/ { s/.*// X; ;s/\n/||/gp }'당신의 파일|
        정렬 |
        네덜란드바 |
        sed -e 's/ *\([0-9]*\)[^|]*||\(.* RDF:about="rdf:#$CHROME\)[0-9]*/\2\ 1/' -e 's/||/\n/g'

참고: 이를 위해서는 (아마도) GNU sed가 필요합니다.

개요

  • sed파일을 정렬에 적합한 형식으로 변환하는 데 사용됩니다 (자세한 내용은 아래 참조).
  • 의 출력을 정렬합니다 sed.
  • 줄 번호를 적용(추가)합니다. 적절한 숫자를 생성하는 명령을 사용하십시오. 나는 그것을 좋아 nl -ba하지만 cat -n그것은 잘 작동하며 아마도 다른 옵션이 있을 것입니다.
  • sed줄의 시작 부분에서 줄 번호를 제거하고 끝에 삽입하는 데 사용됩니다 CHROME. 데이터를 원래 형식으로 복원합니다.

세부정보 - 첫 번째 sed명령

sort명령은 각 행을 레코드로 처리합니다. 따라서 입력 파일에서 각 (구분된) 레코드를 가져와 모든 줄을 연결하여 하나의 긴 줄을 만듭니다. 또한 name정렬 키를 지정하지 않도록 값을 행 시작 부분에 복사합니다.

  • -n자동 인쇄를 비활성화하려면 이 옵션을 사용합니다 . 이라고 말한 경우에만 줄이 인쇄됩니다 p.

  • H모든 라인에서 실행합니다. 그러면 현재 행이 예약된 공간에 추가됩니다. 논리적으로는 그게 더 합리적일 수도 있겠네요복사해당 <줄을 예약된 공간에 추가하고(명령 사용 h) 모든 후속 줄을 추가합니다. 나는 이 접근 방식을 무작위로 선택했습니다.

    <빈 예약 공간에 행을 추가하기 때문에 집계 레코드의 시작 부분에 추가 줄바꿈이 있다는 점에 유의하세요 .

  • 가 포함된 줄을 찾고 />선택적으로 앞뒤에 공백을 추가합니다. 우리가 그것을 찾으면 예약된 공간에 완전한 기록이 있다는 것을 알게 됩니다. 이 줄에서만 다음 명령을 실행하십시오.

    • s/.*//패턴 공간을 지웁니다(즉, 선 지우기 />). 실제로 정보를 버리는 것은 아닙니다. 행은 />이미 예약된 공간에 추가되었습니다(왜냐하면모든행은 예약된 공간에 추가됩니다).
    • x패턴 공간을 바꾸고 공간을 유지합니다. 이는 보유 공간에서 패턴 공간으로 집계된(추가/연결된) 레코드를 검색합니다. 이전 ( ) 명령으로 인해 s/.*//예약된 공간이 지워집니다 .
    • s/.*NS1:name="\([^"]*\)/\1&/이름 필드를 찾아 해당 값을 레코드 시작 부분에 복사합니다. 인용된 문자가 포함된 이름을 사용할 수 있으면 이 작업은 실패합니다.내부에.
    • s/\n/||/gp패턴 공간의 각 개행 문자를 로 대체합니다 ||. (이는 레코드를 라인으로 변환하는 단계입니다.) 이후 p레코드가 인쇄됩니다.

sed예제 파일에 대해 실행하면 첫 번째 명령의 출력은 다음과 같습니다.

AAA Carolinas||<RDF:Description RDF:about="rdf:#$CHROME1"|| NS1:name="AAA Carolinas"||  NS1:urlToUse=""||  NS1:whereLeetLB="off"||  NS1:leetLevelLB="1"||  NS1:hashAlgorithmLB="md5"||  NS1:passwordLength="16"||  NS1:usernameTB="user"||  NS1:counter=""||  NS1:charset="a9b0c8d1e7f2g6h3i5j4klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV123456789"||  NS1:prefix="6%Fl"||  NS1:suffix="I$5g"||  NS1:protocolCB="false"||  NS1:subdomainCB="true"||  NS1:domainCB="true"||  NS1:pathCB="false"||  />
Adobe Forums||<RDF:Description RDF:about="rdf:#$CHROME2"|| NS1:name="Adobe Forums"||  NS1:urlToUse="adobeforums.com"||  NS1:whereLeetLB="off"||  NS1:leetLevelLB="1"||  NS1:hashAlgorithmLB="md5"||  NS1:passwordLength="12"||  NS1:usernameTB="username"||  NS1:counter=""||  NS1:charset="a9b0c8d1e7f2g6h3i5j4klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV"||  NS1:prefix=""||  NS1:suffix=""||  NS1:protocolCB="false"||  NS1:subdomainCB="true"||  NS1:domainCB="true"||  NS1:pathCB="false"||  NS1:pattern0="*adobeforums.com*"||  NS1:patternenabled0="true"||  NS1:patterndesc0=""||  NS1:patterntype0="wildcard"||  />
Adorama||<RDF:Description RDF:about="rdf:#$CHROME3"|| NS1:name="Adorama"||  NS1:urlToUse="adorama.com"||  NS1:whereLeetLB="off"||  NS1:leetLevelLB="1"||  NS1:hashAlgorithmLB="md5"||  NS1:passwordLength="8"||  NS1:usernameTB="username"||  NS1:counter=""||  NS1:charset="a9b0c8d1e7f2g6h3i5j4klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV"||  NS1:prefix=""||  NS1:suffix=""||  NS1:protocolCB="false"||  NS1:subdomainCB="false"||  NS1:domainCB="true"||  NS1:pathCB="false"||  NS1:pattern0="*adorama.com*"||  NS1:patternenabled0="true"||  NS1:patterndesc0=""||  NS1:patterntype0="wildcard"||  NS1:pattern1="www.adoramapix.com*"||  NS1:patternenabled1="true"||  NS1:patterndesc1=""||  NS1:patterntype1="wildcard"||  />

세부정보 - 두 번째 sed명령

  • s/ *\([0-9]*\)[^|]*||\(.* RDF:about="rdf:#$CHROME\)[0-9]*/\2\1/ 선을 여러 부분으로 나눕니다.

    • 0개 이상의 공백.
    • 줄 번호(0개 이상의 숫자)입니다. 이것이 \1그룹이 됩니다.
    • 줄 번호, value name||그 뒤의 탭 문자입니다.
    • 그런데 기록이 올라갔다 RDF:about="rdf:#$CHROME. 이것이 \2그룹이 됩니다.
    • 이전 레코드 번호(0개 이상의 숫자).
    • 암묵적으로 나머지 기록입니다.

    RDF:about="rdf:#$CHROME그런 다음 처음 5개 부분을 줄 번호(새 레코드 번호)의 합계로 바꿉니다. 나머지 레코드는 일치하지 않으므로 명령의 영향을 받지 않습니다.

  • s/||/\n/g||각 줄을 개행 문자로 바꾸어 파일의 원래 여러 줄 구조를 복원(다시 생성)합니다.

확실히, …

...출력을 파일로 보내려면 명령의 마지막 줄 맨 끝에(즉, 두 번째 줄 끝에) 추가하세요. 그러면 이동할 수 있습니다() > your_output_filesedmvyour_output_file원본 파일에. 명령에 대한 옵션을 지정하는 것은 --output=의미  가 없습니다 .-osortsort ~ 해야 하다줄 번호를 적용하는 명령을 입력합니다. 중간 파일을 캡처하려면 그렇게 말하세요.

관련 정보