2010-12-16 3 views
5

일부 텍스트를 증분 값으로 대체하고 싶습니다. 고려 파일 XX :sed 증분 번호

<outro>dfdfd</outro> 
<RecordID>1</RecordID> 
<outro>dfdfd</outro> 
<RecordID>1</RecordID> 
<outro>dfdfd</outro> 
<RecordID>1</RecordID> 
<outro>dfdfd</outro> 

와 sed 명령 : echo $n 명령이 증가되지 않습니다

for n in seq 3;do sed -e 's/<RecordID>\d/<RecordID>'`echo $n`'/' xx; done 

. 또한

Tryed :

n=1; sed -e 's/<RecordID>/<RecordID>'`echo $n ;let n=$n+1`'/g' xx 

하지만 성공

.

만 내가 같이 증가 recordId는 필드가 할 수있는 방법 (더 AWK 또는 펄) 나오지도 않습니다을 것으로 생각 :

<outro>dfdfd</outro> 
<RecordID>1</RecordID> 
<outro>dfdfd</outro> 
<RecordID>2</RecordID> 
<outro>dfdfd</outro> 
<RecordID>3</RecordID> 
<outro>dfdfd</outro> 
+3

이 모든 것은'sed '로 인해 매우 혼란 스럽습니다. 왜냐하면 쉘에서 그것의 외부로 증가시켜야하고 각 라인에 대해 sed의 한 인스턴스를 호출해야하기 때문입니다. 이것은 단지 학업적인 목적이라면, 괜찮아요.하지만 그것은 수학 출생을 할 수 있기 때문에 정말로 'awk'를 사용해야합니다. 사실, 전체 awk 스크립트는이 짧은 줄입니다. awk/RecordID/{sub ("[0-9] +", ++ i)} 1 infile> outfile' – SiegeX

+1

@SiegeX : 전제 sed는 그 일에 맞는 도구가 아닙니다. 레코드 ID가 파일에서 순서대로 표시되지 않는다고 가정 해 봅시다 - 예제에서는 순서대로 보여줍니다. 그러나 숫자가 반드시 단조롭게 증가하거나 순차적으로 나타나는 것은 분명하지 않습니다 ... 'awk'가 캡처를 처리하고 라인의 일부 수정? 나의 의심은 '아주 쉽지 않다'; 그 시점에서 필자는 Perl로 향했다. (비록 내가 Python을 Perl에 완전히 적합한 대안으로 받아들이 겠지만 - 나는 단지 Perl을 Python보다 더 잘 알고있다.) 어떤 전망? –

+1

@Jonathan awk로 무언가를 잘못하고 싶을 때, 일반적으로 연관 배열을 사용해야한다. 그리고 조금 어색한 (아무 말장련도 의도하지 않음) 수 있지만 분명히 "아주 쉽게"카테고리에 넣지 않을 것입니다. O/P의 입력이 어떻게 변화하는지 알고 싶지는 않지만, awk의 연관 배열을 철저히 사용하여 예를 들어 보았습니다. http://stackoverflow.com/questions/4443583/bash-scripts-that-analytics-reports-files/4445671 # 4445671 – SiegeX

답변

5
while read line; do n=$((++n)) && echo $line|sed -e 's/[0-9]/'$(($n))'/' ; done < patt 
+1

두 번째'$ (())'는 불필요합니다. 단지'$ n'을 사용하십시오. 읽기 라인 동안 –

+0

; if [ "$ (echo $ line | grep Re)"]; 다음 N = $ ((+ + N)) && 에코 $ 선 | 나오지도 -e '의/[0-9] /'$ n을 다른 '/' : Fi를 완료 <패티 – Someguy

+0

브래킷, 따옴표 및 명령 대체는 주석의 버전에서 불필요합니다 :'echo "$ line"| grep -qs Re' –

2

먼저, sed\d을 이해하지 않습니다. 대신 [0-9] 또는 [[:digit:]]을 사용하십시오.

두 번째로 for n in seq 3n을 "seq"및 "3"으로 설정합니다. for n in $(seq 3) 또는 (Bash에서는) for n in {1..3}을 사용하십시오.

셋째, 교체 결과를 저장해야합니다. sed 버전이 -i (in-place)을 지원하는 경우이를 사용하거나 sed ... xx > xx.tmp && mv xx.tmp xx을 사용해야 할 수도 있습니다.

넷째, 변경하려는 행을 선택해야합니다.

가 모두 함께 넣고이 작동하지만, 매우 느릴 수 : Perl과 awk는 사용할 수 없습니다 그 문제의 성명에도 불구하고

for n in $(seq 3); do sed -e $(($n*2))'s/<RecordID>[[:digit:]]/<RecordID>'$n'/' xx > xx.tmp && mv xx.tmp xx; done 
+0

Charles의 대답의 일반적인 형식이 아마 더 효율적입니다. –

+0

첫 번째 패스는 0..9에서 2까지의 모든 ID 값을 매핑합니다. 두 번째 패스는 모든 2를 4로 매핑합니다. 세 번째 패스는 모든 4를 6으로 매핑합니다 ... 그렇지 않습니까? –

+0

@Jonathan : 아니요,'$ (($ n * 2))'이 어떤 행을 조작할지 선택하기 때문입니다. –

4

, 지금까지 주어진 답은 sed이 아니라는 것을 보여 이 작업을위한 올바른 도구. 두 가지 대답은 극히 제한된 데이터 집합에서만 작동하며 극히 소수의 데이터 집합에서만 정상적으로 작동합니다.

sed을 사용하면 수천 개의 레코드를 처리 할 수있는 적절한 방법이 없습니다. 3 개의 레코드 ID (힌트 : 맵핑 된 3을 4로 맵핑하지 않도록 2에서 3으로 맵핑하기 전에 3에서 4로 맵핑해야 할 수도 있음)을 처리 할 때 조심스럽게 솔루션을 해킹 할 수 있습니다.

Perl 또는 Python을 사용하면 가능합니다.

perl -e 's{<RecordID>(\d+)</RecordID>}{$n=$n+1; "<RecordID>$n</RecordID>"}e' 

'작업에 적합한 도구 사용'의 경우가 대부분입니다. sed은 그것이 설계된 작업 (그리고 설계되지 않은 많은 좋은 것들)을위한 훌륭한 도구입니다. 그러나 이것은 과도하게 강조하고 있습니다.

+4

+1 올바른 도구. 그러나 때로는 두근 두근이 필요하고 단지 스크루 드라이버 만있는 못에 직면하게됩니다. 그럼 넌 어떻게하지? (나는 스크류 드라이버를 마시 며 "손톱을 조이십시오"라고 말합니다.) 그러면 –

+0

어떻게 이것을 파일과 함께 사용합니까? – olivervbk

+0

@OliverKuster : 스크립트의'-e '...'부분 다음에 파일 이름을 지정합니다. 그러면 출력이 표준 출력에 기록됩니다. 출력물이 원본 파일을 덮어 쓰게하려면'-e' 앞에'-i.bak'와 같은 옵션을 추가하십시오 (그러나 먼저 변경 사항을 테스트하십시오). –

0

sed로 이것을하는 진정한 방법은 물론 쉘에서 루핑의 필요성을 제거하는 것입니다. Denis의 주소 일치 프로그램과 같은 것을 사용하여 범위를 좁히고 script in sed's info pages의 표현식을 사용하십시오. 어휘 적으로 숫자를 증가시키고 산술은 포함시키지 않습니다. 그것이하는 유일한 트릭은 캐리를 돌보는 것입니다.