SED는 문자열 내의 문자열을 대체합니다.

SED는 문자열 내의 문자열을 대체합니다.

다음 스크립트가 있습니다.

originalLine='<com.whatsapp.voipcalling.VideoCallParticipantViewLayout android:id="@id/video_participant_views" android:layout_width="fill_parent" android:layout_height="fill_parent"/>'

escParamToChange="android:layout_width"
value="10dip"

replacementLine=$(echo ${originalLine} | sed -E 's/'${escParamToChange}'=[^ ]*/'${escParamToChange}'="'${value}'"/')

echo ${replacementLine}

"android:layout_width" 값을 "10dip"으로 바꾸려고 합니다.

잘 작동하고 출력은 다음과 같습니다.

<com.whatsapp.voipcalling.VideoCallParticipantViewLayout android:id="@id/video_participant_views" android:layout_width="10dip" android:layout_height="fill_parent"/>

하지만 "escParamToChange"를 "android:layout_height"로 변경하면 다음과 같은 결과가 나옵니다.

<com.whatsapp.voipcalling.VideoCallParticipantViewLayout android:id="@id/video_participant_views" android:layout_width="fill_parent" android:layout_height="10dip"

마지막 "/>"도 제거됩니다.

작동하게 하려면 무엇을 변경해야 합니까?

감사해요

답변1

노력하다

replacementLine=$(echo ${originalLine} | sed -E 's/('${escParamToChange}'=)"[^"]+"/\1"'${value}'"/')
  • \1캡처된 그룹 바꾸기 ('${escParamToChange}'=)(바로가기)
  • "[^"]+""일치 항목은 "가 아닌 하나 이상의 문자로 시작하고 그 뒤에는 종결자 값이 옵니다."

"sed(GNU sed) 4.4"에 적용됩니다.

$ originalLine='<com.whatsapp.voipcalling.VideoCallParticipantViewLayout android:id="@id/video_participant_views" android:layout_width="fill_parent" android:layout_height="fill_parent"/>'
$ value="10dip"
$ for escParamToChange in android:layout_width android:layout_height; do echo ${originalLine} | sed -E 's/('${escParamToChange}'=)"[^"]+"/\1"'${value}'"/'; done
<com.whatsapp.voipcalling.VideoCallParticipantViewLayout android:id="@id/video_participant_views" android:layout_width="10dip" android:layout_height="fill_parent"/>
<com.whatsapp.voipcalling.VideoCallParticipantViewLayout android:id="@id/video_participant_views" android:layout_width="fill_parent" android:layout_height="10dip"/>

답변2

발견한 대로 이 명령은 너무 많은 항목을 삭제합니다.

$ echo "${originalLine}" | sed -E 's/'${escParamToChange}'=[^ ]*/'${escParamToChange}'="'${value}'"/'
<com.whatsapp.voipcalling.VideoCallParticipantViewLayout android:id="@id/video_participant_views" android:layout_width="fill_parent" android:layout_height="10dip"

그러나 이 명령은 작동합니다.

$ echo "${originalLine}" | sed -E 's/'${escParamToChange}'=[^ /]*/'${escParamToChange}'="'${value}'"/'
<com.whatsapp.voipcalling.VideoCallParticipantViewLayout android:id="@id/video_participant_views" android:layout_width="fill_parent" android:layout_height="10dip"/>

문제 [^ ]*는 입니다. 로 />바꾸면 일치에서 제외 됩니다 .[^ ]*[^ /]/>

위의 한 가지 잠재적인 문제는 ${escParamToChange}및 가 ${value}명령줄에 따옴표 없이 표시된다는 것입니다. 공백이나 기타 쉘 활성 문자가 포함되어 있으면 원치 않는 결과가 발생할 수 있습니다.

대안: awk를 사용하세요

Awk의 장점은 변수를 합리적인 방식으로 처리하므로 sed 명령에 쉘 변수를 넣을 때 발생할 수 있는 몇 가지 함정을 피할 수 있다는 것입니다. 제 생각에는 인용 문제도 단순화됩니다.

$ echo "${originalLine}" | awk -v regex="${escParamToChange}=[^ /]*" -v new="${escParamToChange}=\"${value}\"" '{gsub(regex, new)} 1'
<com.whatsapp.voipcalling.VideoCallParticipantViewLayout android:id="@id/video_participant_views" android:layout_width="fill_parent" android:layout_height="10dip"/>

답변3

xqXML 인식 편집 도구인 를 사용하세요 .https://kislyuk.github.io/yq/, 속성 수정:

replacementLine=$( printf '%s\n' "$originalLine" |
        xq -x \
                --arg attrib "@$escParamToChange" \
                --arg value "$value" \
                '(.[] | .[$attrib]) |= $value' )

printf '%s\n' "$replacementLine"

내부 변수에서 변경할 속성 이름 attrib과 변경할 값을 가져옵니다 value. 경로 표현식은 .[] | .[$attrib]변경하려는 속성 이름이 있는 모든 속성으로 확장됩니다(속성 이름은 @하위 노드가 아닌 속성으로 지정하는 명령줄의 접두사입니다).

관련 정보