2014-07-07 5 views
2

저는 일부 소프트웨어 패키지를 일부 Linux 임베디드 시스템으로 이식하기 위해 buildroot 패키지를 사용합니다. 일부 소프트웨어 패키지는 스테이징 디렉토리에 대한 참조가있는 일반 텍스트 스크립트 및/또는 라이브러리 제어 파일도 생성합니다. 배포를 위해 소프트웨어 패키징 단계에서 준비 디렉토리에 대한 참조를 제거해야합니다. SED를 사용하여 그러한 참조를 제거하는 데 문제가 없습니다. 그러나이 처리는 중복 문자열의 일부 원하지 않는 패턴을 남겨두고 아래와 같이 발췌했습니다. 그러한 중복을 제거하기 위해 SED를 사용할 수 있는지 알고 싶습니다.SED로 중복 문자열 제거

: '의 dependency_libs ='가 탈락하고, 다음과 같이 현재 개정. 여기에 필요한 항목을 발췌하여 간결하게하려고 시도했으며 어떤 중복도 포함되어 있지 않기 때문에 'dependency_libs ='을 여기에 포함시키지 않았습니다. 외관상으로는, 그것은 뒤에 오는 건의 한 해결책의 몇몇에 중요한 부분을한다. 그러므로 나는 후손을 위해 그것을 여기에서 수정했다.

주 2 : 난 그냥에 약간의 버그를 발견은 @potong에서 스크립트를 나오지도. 중복 문자열이 마지막 공간 인 경우 sed 스크립트가 실패합니다. 이 경우 첫 번째의 dependency_libs = '행은 부분적으로 sed 개의 스크립트를 실패합니다. 두 번째의 dependency_libs = '줄에는 줄 끝 부분에 작은 따옴표 바로 앞에 공백이 포함되어 있으며 문제없이 sed 스크립트를 통과합니다. 차이점을 보여주기 위해 여기를 수정했습니다.

cppflags=-I/usr/include -I/include -I/usr/include -I/include -I${includedir}/mine 
cxxflags=-I/usr/include -I/include -I/usr/include -I/include -I${includedir}/mine 
Cflags: -I/usr/include -I/include -I/usr/include -I/include -I${includedir}/mine 
Libs: -L/usr/lib -L/lib -L/usr/lib -L/lib -L${libdir} -lmine${suffix} 
dependency_libs='-L/usr/lib -L/lib -L/usr/lib -L/lib -L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib -L/usr/lib -L/lib -L/usr/lib -L/lib' 
dependency_libs='-L/usr/lib -L/lib -L/usr/lib -L/lib -L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib -L/usr/lib -L/lib -L/usr/lib -L/lib ' 

그래서이 될 것이라고 :

cppflags=-I/usr/include -I/include -I${includedir}/mine 
cxxflags=-I/usr/include -I/include -I${includedir}/mine       
Cflags: -I/usr/include -I/include -I${includedir}/mine       
Libs: -L/usr/lib -L/lib -L${libdir} -lmine${suffix} 
dependency_libs='-L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib' 
dependency_libs='-L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib' 

답변

0

이 당신을 위해 작동 할 수 있습니다

awk -F- ' 
    { 
    for(i = 2; i <= NF; ++i) a[$i] = 1; 
    printf("%s", $1) 
    for(x in a) printf("-%s ", x) 
    print"" 
    delete a 
    } 
' 

출력 :

cppflags=-I${includedir}/mine -I/include -I/usr/include 
cxxflags=-I${includedir}/mine -I/include -I/usr/include 
Cflags: -I${includedir}/mine -I/include -I/usr/include 
Libs: -L${libdir} -lmine${suffix} -L/lib -L/usr/lib 

주의는 유지하지 않습니다 디렉토리 순서 및 i 여기 저기에 여분의 공간을 추가합니다.

당신이 디렉토리의 순서를 유지해야하고 gawk를 사용할 수있는 경우, 시도 :

gawk -F- ' 
    BEGIN {PROCINFO["sorted_in"] = "@val_num_asc"} 
    { 
    for(i = 2; i <= NF; ++i) 
     if (!($i in a)) 
     a[$i] = i; 
    printf("%s", $1) 
    for(x in a) printf("-%s ", x) 
    print"" 
    delete a 
    } 
' 

출력 :

cppflags=-I/usr/include -I/include -I${includedir}/mine 
cxxflags=-I/usr/include -I/include -I${includedir}/mine 
Cflags: -I/usr/include -I/include -I${includedir}/mine 
Libs: -L/usr/lib -L/lib -L${libdir} -lmine${suffix} 

또는 비 GNU를 사용하여 동일한 결과를 얻을 수 있습니다 awk like this :

물론, 여분의 sp를 제거해야하는 경우 에이스, 당신은 tr -s ' ' 통해 출력 파이프 수 있습니다.

0

필드 - 단일 행의 상호 관련 부분을 처리 할 수있는 유틸리티가 필요하기 때문에 sed이 작동하지 않을 것이라고 생각합니다.@ooga's answer 같이 awk

사용은 옵션이지만, 여기에 순수 bash 솔루션입니다.

참고 : 성능상의 이유로 작은 입력 파일에 대한

  • 만에 적합합니다.
  • 입력에 공백이 포함 된 옵션이 없다고 가정합니다.
  • 옵션의 입력 순서가 유지됩니다 (옵션 사이의 공백이 정규화 됨).
#!/usr/bin/env bash 

while read -r line; do 
    # Split line into prefix, separator, options array. 
    [[ $line =~ ^([^=:]+)([:=]\ *)(.*)$ ]] 
    prefix=${BASH_REMATCH[1]} 
    sep=${BASH_REMATCH[2]} 
    read -ra optArray <<<"${BASH_REMATCH[3]}" 
    # Loop over options array and build up a list without duplicates. 
    dedupOptList='' 
    for opt in "${optArray[@]}"; do 
    [[ " $dedupOptList " == *" $opt "* ]] || dedupOptList+=" $opt" 
    done 
    # Finally, rebuild the line with the deduplicated options list and print. 
    printf '%s%s%s\n' "$prefix" "$sep" "${dedupOptList:1}" 
done < file 
1

이 당신을 위해 작동 할 수 있습니다 (GNU 나오지도) :

sed -r ':a;s|((-[IL]/\S+\s).*)\2|\1|;ta' file 

이 하나 이상의 비 - 공백으로 다음 -I/ 또는 -L/으로 태초 문자열과 반복되는 공간을 찾습니다 두 번째 발생을 제거합니다. 대체가 발생하면 대체가 발생하지 않을 때까지 프로세스가 반복됩니다.

+0

제안 사항은 정상적으로 작동합니다. 불행히도 저에게 파일에 "-L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib"와 같은 내용이 들어 있으면 SED 스크립트는 "-L/lib libiconv- full/lib libintl-full/lib "로 변경하십시오. 이 문제를 해결할 수있는 방법이 있습니까? – Mazilo

+0

@ user3767809 위에 수정 된 버전을 사용해보십시오. 그러나 내가 제공 한 데이터로 원본 버전을 테스트했을 때 나는 기대했던 결과를 얻지 못했습니다. 아마도 모든 가능한 조합과 예상 결과를 반영하도록 질문을 수정해야합니까? – potong

+0

귀하의 제안에 따라, 나는 * '- L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib'* 라인을 포함하도록 OP를 수정했습니다. 또한 수정 된 버전의 * sed * 스크립트를 여러 소프트웨어 패키지의 buildroot * Makefile * 파일에 추가했으며 문제없이 예상대로 작동합니다. 지금까지 귀하의 제안은 아름답게 작동합니다. 고맙습니다. – Mazilo