sed - 仅替换第 N 次出现的函数

sed - 仅替换第 N 次出现的函数

在下面的函数中(删除) 我只想替换“NTH_OCCUR”(0~n)的出现。我该怎么做?我已经测试了很多方法!

f_ez_sed:

f_ez_sed() {
    : 'Facilitate the use of "sed" functionality .

    Args:
        TARGET (str): Value to be replaced by the REPLACE value.
        REPLACE (str): Value that will replace TARGET.
        FILE (str): File in which the replacement will be made.
        NTH_OCCUR (Optional[int]): Perform the operation only on the indicated 
    occurrence.
    '

    TARGET=$1
    REPLACE=$2

    f_ez_sed_ecp "$TARGET" 1
    TARGET=$F_EZ_SED_ECP_R
    f_ez_sed_ecp "$REPLACE" 1
    REPLACE=$F_EZ_SED_ECP_R

    FILE=$3
    NTH_OCCUR=$4

    ((NTH_OCCUR++))
    SED_RPL="'s/$TARGET/$REPLACE/$NTH_OCCURg'"
    eval "sed -i $SED_RPL $FILE"
}

f_ez_sed "Listen 80" "# Listen 80\nListen 8008" "/etc/apache2/listen.conf" 1

f_ez_sed_ecp:

F_EZ_SED_ECP_R=""
f_ez_sed_ecp() {
    : 'Escape strings to the "sed" command.

    Args:
        VAL_TO_ECP (str): Value to be "escaped".
        DONT_ECP_NL (Optional[int]): 1 - Don't escape "\n" (newline); 
    0 - Escape "\n" (newline). Standard 1.
        DONT_ECP_SQ (Optional[int]): 0 - Don't escape "'" (single quote); 
    1 - Escape "'". Standard 0.

    Returns:
        F_EZ_SED_ECP_R (str): Escaped Value.
    '

    VAL_TO_ECP=$1
    DONT_ECP_NL=$2
    if [ -z "$DONT_ECP_NL" ] ; then
        DONT_ECP_NL=1
    fi
    DONT_ECP_SQ=$3
    if [ -z "$DONT_ECP_SQ" ] ; then
        DONT_ECP_SQ=0
    fi
    F_EZ_SED_ECP_R=$VAL_TO_ECP
    if [ ${DONT_ECP_NL} -eq 1 ] ; then
        F_EZ_SED_ECP_R=$(echo "$F_EZ_SED_ECP_R" | sed 's/\\n/C0673CECED2D4A8FBA90C9B92B9508A8/g')
    fi
    F_EZ_SED_ECP_R=$(echo "$F_EZ_SED_ECP_R" | sed 's/[]\/$*.^|[]/\\&/g')
    if [ ${DONT_ECP_SQ} -eq 0 ] ; then
        F_EZ_SED_ECP_R=$(echo "$F_EZ_SED_ECP_R" | sed "s/'/\\\x27/g")
    fi
    if [ ${DONT_ECP_NL} -eq 1 ] ; then
        F_EZ_SED_ECP_R=$(echo "$F_EZ_SED_ECP_R" | sed 's/C0673CECED2D4A8FBA90C9B92B9508A8/\\n/g')
    fi
}

“listen.conf”内容:

#Listen 12.34.56.78:80
#Listen 80
#Listen 443


Listen 80


<IfDefine SSL>
    <IfDefine !NOSSL>
        <IfModule mod_ssl.c>

            Listen 443

        </IfModule>
    </IfDefine>
</IfDefine>

答案1

注意

  • /g将取代所有发生
  • 默认情况下,仅替换第一个。

我会做

TARGET=$1
REPLACE=$2
FILE=$3
NTH_OCCUR=$4

while [ $NTH_OCCUR -gt 0 ]
do

  sed -i "s/$TARGET/$REPLACE/" $FILE"
  NTH_OCCUR=$((NTH_OCCUR - 1))

done

并调用

f_ez_sed "^Listen 80" "# Listen 80\nListen 8008" "/etc/apache2/listen.conf" 1

您必须使用^Listen行首锚定。

答案2

我找不到使用“sed”在特定位置进行替换的方法!坦白说,我不知道您是否可以仅使用“sed”来做到这一点!但是,使用下面的代码可以解决问题。显然不是有效的。

f_ez_sed() {
    : 'Facilitate the use of "sed" functionality .

    Args:
        TARGET (str): Value to be replaced by the REPLACE value.
        REPLACE (str): Value that will replace TARGET.
        FILE (str): File in which the replacement will be made.
        NTH_OCCUR (Optional[int]): Perform the operation only on the indicated 
    occurrence.
    '

    TARGET=$1
    REPLACE=$2

    f_ez_sed_ecp "$TARGET" 1
    TARGET=$F_EZ_SED_ECP_R
    f_ez_sed_ecp "$REPLACE" 1
    REPLACE=$F_EZ_SED_ECP_R

    FILE=$3
    NTH_OCCUR=$4
    if [ ${NTH_OCCUR} -gt -1 ] ; then
        ((NTH_OCCUR++))
        for (( i=0; i<$(( $NTH_OCCUR - 1 )); i++ )) ; do
            SED_RPL="'0,/$TARGET/s//£§¢¬¨/g'"
            eval "sed -i $SED_RPL $FILE"
        done
        SED_RPL="'0,/$TARGET/s//$REPLACE/g'"
        eval "sed -i $SED_RPL $FILE"
        SED_RPL="'s/£§¢¬¨/$TARGET/g'"
        eval "sed -i $SED_RPL $FILE"
    else
        SED_RPL="'s/$TARGET/$REPLACE/g'"
        eval "sed -i $SED_RPL $FILE"
    fi
}

相关内容