다음 스크립트가 있습니다.
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
xq
XML 인식 편집 도구인 를 사용하세요 .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]
변경하려는 속성 이름이 있는 모든 속성으로 확장됩니다(속성 이름은 @
하위 노드가 아닌 속성으로 지정하는 명령줄의 접두사입니다).