Bash를 사용하여 xml 파일 추가

Bash를 사용하여 xml 파일 추가

포럼의 좋은 사람이 이 스크립트를 만드는 데 도움을 주었지만 내가 던지는 모든 것은 오류를 출력하며 왜, 무엇이 문제인지 전혀 모릅니다. bash test.sh를 요청하면 우분투 터미널에서 모든 스크립트를 실행했습니다.

내 목표는 여러 .xml 파일에 태그를 추가하는 것이지만 process></process>일부 파일에는 1~100개의 태그가 있을 수 있습니다.

예:

 - jfksaJDFH
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>
 - jdhkjasdh
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>

스크립트 이후:

 - jfksaJDFH
 - <process>value="1"</process>
 - <process>value="2"</process>
 - <process>value="3"</process>
 - <process>value="4"</process>
 - jdhkjasdh
 - <process>value="5"</process>
 - <process>value="6"</process>
 - <process>value="7"</process>
 - <process>value="8"</process>

스크립트:

#!/bin/bash

dir="/mnt/Desktop/test/"

while IFS= read -r -d '' file
do
    i=1
    while IFS= read -r -u 3 line
    do
        if [[ $line = '<process></process>' ]]; then
           echo "<process>value=\"$((i++))\"</process>"
        else
           echo "$line"
        fi
    done 3< "$file" > "$file.xml"
done < <(find $dir -type f -name \*.xml -print0)

위 스크립트가 실행되면 마지막 스크립트를 제거하십시오.<process>value=""</process>

스크립트를 다음과 같이 수정합니다.

while IFS= read -r -d '' file
do
    i=1
    while IFS= read -r -u 3 line
    do
        if [[ $line = '<process></process>' ]]; then
           echo "$line"
        else
           echo "<process>value=\"$((i++))\"</process>"
        fi
    done 3< "$file" > "$file.xml"
done < <(find $dir -type f -name \*.xml -print0)

파일의 출력은 다음과 같습니다.

<process>value="1"</process>
<process>value="2"</process>
<process>value="3"</process>
<process>value="4"</process>
<process>value="5"</process>
<process>value="6"</process>
<process>value="7"</process>
<process>value="8"</process>
<process>value="9"</process>
<process>value="10"</process>
<process>value="11"</process>
<process>value="12"</process>
<process>value="13"</process>
<process>value="14"</process>
<process>value="15"</process>
<process>value="16"</process>
<process>value="17"</process>
<process>value="18"</process>
<process>value="19"</process>
<process>value="20"</process>
<process>value="21"</process>
<process>value="22"</process>
<process>value="23"</process>

즉, 이는 페이지의 다른 모든 항목을 추가하지만 제거합니다.

답변1

이 스크립트를 파일에 넣으세요(예: 'increase.awk'):

BEGIN { i = 1 }
/.*<process>value=""<\/process>.*/ { split($0, a, "value=\"\"") ; print a[1] "value=\"" i++ "\"" a[2] ; next }
/.*/ { print $0 }

그런 다음 전화하십시오.

gawk -f increase.awk < yourinputfile

설명: awk에서 split("string", a, "separatorstring")"separatorstring"을 구분 기호로 사용하여 "string"을 a라는 배열로 분할합니다. 따라서 a[1]에는 첫 번째 "구분자 문자열"까지의 모든 내용이 포함되고, a[2]에는 줄 끝이나 다음 "구분자 문자열"까지의 모든 내용이 포함됩니다.

답변2

이 XML을 사용하지 마세요. 원한다면 생각해 보십시오. XML은 공백을 적극적으로 무시하는 구조화된 데이터 유형입니다. eg <attr name="fish" />및 기타 항목과 같은 단항 태그가 있다는 것은 정규식을 사용하여 한 줄씩 구문 분석하면 언젠가 코드가 이상하게 충돌한다는 것을 의미합니다.

이를 수행하는 방법은 XML 파서를 사용하는 것입니다. 어느 것을 사용할지는 개인 취향의 문제이지만 저는 스크립팅 XML::Twig(perl 모듈)을 좋아합니다.

설명된 대로 문제를 해결하려면:

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

sub increment_value {
    my ( $twig, $process ) = @_;
    my ($value) = ( $process->text =~ m/(\d+)/ );
    print "Got $value\n";
    if ( defined ( $value ) ) { 
        $process->set_text( 'value="' . ++$value . '"' );
    } 
    else {
        $process -> delete;
    }
}

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented',
    'twig_handlers' => { 'process' => \&increment_value },
);
$twig->parsefile( 'your_file.xml'  );
$twig->print;    #prints to stdout.

process이는 텍스트를 추출, 변환 및 대체하는 요소별 "처리기"를 트리거합니다 .

답변3

스크립트를 다시 작성할 때 if-then-else 구문의 논리가 복원되었다는 사실을 알고 계셨습니까?

아래 주석 줄 1과 2의 위치를 ​​확인하세요. 다시 작성된 코드에서 이를 반대로 했습니다.

그리고 IFS=는 -r -d '' 파일을 읽습니다.
하다
    나는=1
    그리고 IFS= read -r -u 3줄
    하다
        if [[ $line = '' ]];
           echo "value=\"$((i++))\"" # 라인 1******************
        기타
           echo "$line" # 2번째 줄********************
        필리핀 제도
    3개의 "$file.xml"을 완료하세요.
완벽한

관련 정보