미리 만들어진 sed 문자열이 문자열을 올바르게 해석하지 않습니다.

미리 만들어진 sed 문자열이 문자열을 올바르게 해석하지 않습니다.

내 코드는 두 개의 서로 다른 파일이 동일한 파일에서 줄 번호를 찾은 다음 파일 중 하나에서 해당 줄 번호를 제외한 모든 줄을 제거하도록 설계되었습니다. 이를 위해 sed에서 실행하고 싶은 미리 만들어진 sed 문자열을 만들었지만 오류가 발생합니다.

sed: -e expression #1, char 3: unknown command: `;'

내 미리 만들어진 sed 문자열은 다음과 같습니다

echo ${_sedstr}
1;2;7;11;12;13;15;17;22!d

내 의도는 sed 명령에서 이 변수를 사용하여 문자열의 줄을 제외하고 ${_edit} 파일의 모든 줄을 삭제하는 것입니다.

sed -i.bak -e ${_sedstr} ${_edit} 

${_sedstr} 주위에 작은따옴표/큰따옴표를 배치하고 백슬래시 "\"로 따옴표를 이스케이프 처리하는 모든 조합을 시도했지만 코드가 예상대로 실행되는 데 여전히 문제가 있는 것 같습니다.


제가 달성하고 싶은 것의 예는 다음과 같은 ${_edit}입니다:

hello
my
name
is
John
Doe

표현식을 사용하여 sed -i.bak -e '1;2;4!d' ${_edit}파일을 다음으로 출력하고 싶습니다.

hello
my
is

1, 2, 4를 제외한 모든 행을 삭제합니다.

답변1

이는 올바른 구문이 아닙니다 sed.

아마도 sed '1d;2d;7d'그렇지 않을 것이다sed '1;2;7d'

1, 2, 7을 제외한 모든 명령을 제거하려면 다음을 사용하십시오 sed -e 1b -e 2b -e 7b -e d(portable/POSIXly를 사용하여 명령을 ;구분할 수는 없지만 b개행 문자는 사용할 수 있습니다).

그래서:

sed_script='1d;2d;7d'
sed -i.back -e "$sed_script" -- "$_edit"

또는:

sed_script='
  1b
  2b
  7b
  d
'
sed -i.back -e "$sed_script" -- "$_edit"

매개변수 확장을 인용해야 합니다. 바라보다언제 큰따옴표가 필요합니까?. 그리고 --옵션 구분 기호를 잊지 마세요 . 단지 , 당신은 여기서 이것을 cmd -- "$arg"원하지 않을 뿐입니다 .cmd "$option_or_arg"

유지/삭제할 행이 많은 경우 GNU를 사용하여 다음을 awk사용할 수 있습니다.

LINES_TO_KEEP='1;2;7;...' gawk -i /usr/share/awk/inplace.awk -e '
  BEGIN {
    split(ENVIRON["LINES_TO_KEEP"], a, ";")
    for (i in a) keep[a[i]]
  }
  FNR in keep' -E /dev/null "$_edit"

(이것은 이라는 이름의 파일에서는 작동하지 않습니다 . 대신 -을 사용해야 합니다 .)_edit=./-_edit=-

사용하지 마세요-i inplace현재 작업 디렉터리(as or)에서 확장 기능을 먼저 gawk로드 하려고 하면 누군가가 해당 디렉터리에 악성 코드를 심었을 수 있습니다. 시스템과 함께 제공되는 확장 프로그램 의 경로 는 다를 수 있습니다. 출력을 참조하세요.inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

답변2

조금은 엉뚱 sed하지만 답변이 되었으니... 순서는 걱정하지 않고 동일한 페어링 라인만 걱정한다면...

join <(sort file1) <(sort file2) > matchedlines

줄 번호를 알 필요도 없고 에 배열을 전달할 필요도 없습니다 awk.

관련 정보