두 패턴 사이의 줄을 삭제합니다. 단, 그 사이에 특정 문자열이 있는 경우에만 해당됩니다.

두 패턴 사이의 줄을 삭제합니다. 단, 그 사이에 특정 문자열이 있는 경우에만 해당됩니다.

예를 들어 다음 내용이 포함된 파일이 있습니다.

eggs
bacon
cereal

eggs
bacon
cheese
cereal

산출:

eggs
bacon
cereal

eggs이 예에서는 단어 와 사이에 있는 줄을 삭제하고 싶지만 그 사이에 cereal포함된 경우에만 가능합니다 .cheese

을 사용하여 어떻게 이 작업을 수행할 수 있습니까 sed?

좀 더 구체적으로 요청받았기 때문에 기본적으로 제가 하고 싶은 일은 다음과 같습니다. 이를 통해 더 명확해지기를 바랍니다.

WeaponData
{
    TextureData
    {
                "crosshair"
                {
                                "file"  "vgui/replay/thumbnails/"
                                "x"             "0"
                                "y"             "0"
                                "width"         "64"
                                "height"        "64"
                }
                "weapon"
                {
                                "file"          "sprites/bucket_bat_red"
                                "x"             "0"
                                "y"             "0"
                                "width"         "200"
                                "height"                "128"
                }
                "weapon_s"
                {       
                                "file"          "sprites/bucket_bat_blue"
                                "x"             "0"
                                "y"             "0"
                                "width"         "200"
                                "height"                "128"
                }

                "ammo"
                {
                                "file"          "sprites/a_icons1"
                                "x"             "55"
                                "height"    "15"
                }

                "crosshair"
                {
                    "file"      "sprites/crosshairs" <---
                    "x"     "32"
                    "y"     "32"
                    "width"     "32"
                    "height"    "32"
                }

                "autoaim"
                {
                    "file"      "sprites/crosshairs"
                    "x"     "0"
                    "y"     "48"
                    "width"     "24"
                    "height"    "24"
                }
    }
}

내가 시도한 명령은 다음과 같습니다.

sed '/"crosshair"/,/}/d' file.txt

이 명령은 사이에 줄이 있는지 여부에 관계없이 처음부터 "crosshair"마지막까지 삭제합니다 .}"sprites/crosshairs"

패턴 사이에서 문자열이 발견된 경우 "crosshair"에만 삭제하고 싶습니다 . 그러나 .}"sprites/crosshairs""sprites/crosshairs"

와 같은:

"autoaim"
{
        "file"      "sprites/crosshairs"
        "x"     "0"
        "y"     "48"
        "width"     "24"
        "height"    "24"
}

이는 제거할 수 없습니다. 미리 설명하지 못한 점 깊이 사과드립니다만, 그럴 필요는 없을 것 같았습니다.

don_crissti의 제안은 꽤 잘 작동합니다.sed '/crosshair/,/\}/{H;/\}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile

그러나 출력은 다음과 같습니다.

              ...
              "autoaim"
              {
  }
}

"autoaim"부분적으로 삭제되었지만 완전히 삭제되지는 않았습니다. 보시다시피 포함된 블록이 "sprites/crosshairs"제가 원했던 대로 제거되었지만 autoaim여전히 수정할 수 없습니다.

답변1

sed '/^[[:blank:]]*"crosshair"/,/}/{H;/}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile

작동 방식:

sed '/^[[:blank:]]*"crosshair"/,/}/{         # in this range
H                                            # append each line to hold buffer
/}/!d                                        # delete it if not the end of range
s/.*//                                       # empty the pattern space
x                                            # exchanges buffers
/sprites\/crosshairs/d                       # delete pattern space if it matches
s/.//                                        # remove leading newline, autoprint
}' infile

이는 예제에서와 같이 일치하는 줄 뒤에 ^[[:blank:]]*"crosshair"항상 중괄호로 묶인 줄 블록이 따른다고 가정합니다.

답변2

perl괜찮다면 단락 모드( 옵션 -00)를 사용하고 여러 줄 정규식 일치를 사용할 수 있습니다.

$ cat ip.txt 
eggs
bacon
cereal

eggs
bacon
cheese
cereal

$ perl -00 -ne 'print if !/^eggs.*cheese.*cereal$/ms' ip.txt 
eggs
bacon
cereal

관련 정보