两分钟看懂空格替换

本文探讨了在处理网络编程中URL参数时,如何高效地将空格替换为%20,介绍了两种方法:时间复杂度分别为O(n^2)和O(n),并提供了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:网络编程中,如果说URL参数中含有特殊字符,就拿空格说,可能导致服务器端无法获得正确的的参数值,这个时候就需替换。

1.空格,替换成%20

2.#被替换成%23,等

下边看看,以字符串中空格被替换成%20的场景:例子为 替换 we are happy 中的空格;


总体思想:

1.遍历找空格。

2.移动字符位置。

3.替换空格。

第一种:时间复杂度O(n^2)

如果,从头开始遍历,遇到空格后,需要将空格后的所有字符串后移动两个位置,如果在遇到空格,空格后的字符串又得在移动,看图:


图中意思到就行,主要说明,字符串happy被移动了两次,假设,字符串长度为N,对于每一个空格字符来说,需要移动以后O(n)个字符

对于含有O(n)个空格字符的字符串来说,时间效率就是O(n^2),  这种效率是不可以的。

当然:对于那些重新申请空间来装增长后的字符串的方法,时间上是提高了效率,但同时也消耗了空间,总体来说,不是最好的。

 来看一种相对比较好的:

第二种:时间复杂度O(n)

方法步骤:

1.遍历字符串,统计空格个数,统计字符创总长;

2.每个空格加两个字符长度,计算所有空格替换为响应字符后的总长度;

3.从字符串的后边往前替换,

上图,看图理解:


从后往前替换,p2指向增长后的字符串,p1指向原来字符串,p1和p2同时往前移动,当p1遇到空格时,p2停下来,

在p1的位置插入替换的字符串最后一个字符,例如替换的字符串是“%20“,那么就在p1位置插入0,p1继续前移,p2不动,

相同的方法插入% 2 等字符,当p1指向%前一个字符,p2 开始动,当p1 == p2结束 over

上代码:

//length 为字符数组string的总容量
void ReplaceBlank(char string[], int length)
{
	//如果字符串为空,返回
    if(string == NULL && length <= 0)
        return;

    int originalLength = 0; //originalLength 为字符串string的实际长度
    int numberOfBlank = 0;  //空格数
    int i = 0;
    while(string[i] != '\0')
    {
        ++ originalLength;  //字符串原长统计

        if(string[i] == ' ')
            ++ numberOfBlank; //空格数统计

        ++ i;
    }

    //newLength 为把空格替换成'%20'之后的长度
    int newLength = originalLength + numberOfBlank * 2; 

    if(newLength > length)
        return;

    int indexOfOriginal = originalLength;  //相当于图中的p1
    int indexOfNew = newLength;            //相当于图中的p2
    while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
    {
        if(string[indexOfOriginal] == ' ')
        {
            string[indexOfNew --] = '0';
            string[indexOfNew --] = '2';
            string[indexOfNew --] = '%';
        }
        else
        {
            string[indexOfNew --] = string[indexOfOriginal];
        }

        -- indexOfOriginal;
    }
}
赐教!



转载于:https://www.cnblogs.com/melons/p/5791857.html

<think>我们被要求使用sed替换两个空格之间的内容。注意,用户的问题描述是“替换两个空格之间的内容”,这意味着我们需要匹配两个空格之间的文本并替换它。 然而,从引用[2]和引用[3]中,我们可以看到关于空格替换的一些讨论。特别是引用[2]提到连续空格的处理,引用[3]则展示了一个将单个空格后跟任意字符替换为两个空格的例子(但实际是替换空格和其后的一个字符,然后重复两次匹配内容,这并非我们所需)。 用户真正的需求是:替换两个空格之间的内容。注意,两个空格之间可能没有内容(即连续两个空格),也可能有一些字符。我们需要替换的是两个空格之间的内容,而不是空格本身。 例如,在字符串"a b"(两个空格之间没有内容)和"a hello b"(两个空格之间有"hello")中,我们想要替换的是两个空格之间的部分(可能是空字符串或"hello")。 但是,注意:两个空格之间可能不是连续的,因为两个空格之间可能有其他字符。所以我们需要匹配的是:一个空格,然后是一些字符(可能为空),然后是另一个空格。我们要替换的是中间的那些字符。 因此,模式应该是:`空格(任意字符)空格`。注意,我们想要保留两个空格,只替换中间的内容。 所以,我们可以使用捕获组来捕获两个空格,然后替换中间的部分。在sed中,我们可以这样写: s/ \(空格\)[^ ]*\(空格\) / \1替换内容\2 / 但是,这里有几个问题: 1. 空格在正则表达式中就是空格字符,我们可以用' '表示。 2. 我们想要匹配两个空格之间的任意字符,但是注意,如果两个空格之间有多个单词(即中间还有空格)怎么办?用户的问题没有明确,但通常两个空格之间的内容可能包含空格吗?如果是这样,那么我们需要非贪婪匹配,但sed默认不支持非贪婪匹配,除非使用扩展正则表达式(-E)和.*?(但sed不支持?非贪婪,所以我们可以用[^ ]*来匹配非空格字符,这样就不会跨越到下一个空格)。 因此,我们假设两个空格之间的内容是不包含空格的。如果包含空格,那么问题就复杂了,因为我们会遇到多个空格分隔的情况。 根据用户的问题,我们只考虑两个相邻空格之间的内容(注意,两个空格之间没有其他空格),那么中间的内容就是非空格字符的序列。 所以,我们可以这样写: sed 's/ \([^ ]*\) / 替换内容 /g' 但是,注意:这样写要求两个空格之间如果有内容,必须是非空格字符,而且我们匹配的是两个空格,然后中间有非空格字符,再两个空格?这样写实际上要求四个空格(因为前后各两个)。这显然不对。 修正:我们想要的是两个空格之间夹着一些非空格字符。例如:`a hello b`,我们想把`hello`替换掉。但是,注意,实际字符串中可能是`a hello b`(只有一个空格分隔单词),但用户要求的是两个空格之间的内容,所以输入应该是`a hello b`(即hello前后各有两个空格?)这不太常见。 实际上,用户可能指的是两个连续空格之间的内容(包括两个空格之间的一个非空格字符串)。例如,字符串可能是:`a b`(两个空格)或`a hello b`(两个空格+hello+两个空格)。但用户要求替换的是两个空格之间的内容,那么对于`a b`,两个空格之间没有内容(空字符串),而对于`a hello b`,两个空格之间是"hello"(注意,这里前后各有两个空格,所以实际上是四个空格?)。 我们重新理解:用户可能是指由两个空格分隔的字段。例如,在文本中,字段之间用两个空格分隔,现在要替换第二个字段(即第一个两个空格和第二个两个空格之间的内容)。但问题描述不够清晰。 鉴于引用[2]中提到了连续空格,引用[3]中提到了替换空格,我们可能误解了用户的问题。用户可能实际上是想替换两个空格之间的内容,但这里的两个空格是指定界符,即用两个空格作为字段的分隔,然后替换其中某个字段。 但是,用户的问题描述是“替换两个空格之间的内容”,所以我们还是按照字面意思:匹配两个空格之间的内容(即被两个空格夹在中间的内容)并替换。 因此,我们设计如下: 模式:`空格(需要替换的内容)空格` 替换:`空格(新内容)空格` 注意,我们不想替换空格,只想替换中间的内容。 在sed中,我们可以使用捕获组来保留空格,然后替换中间的部分。 例如: sed 's/ \([^ ]*\) / 新内容 /g' 但是,这个命令只能匹配单个空格之间的内容,而不是两个空格。实际上,这个命令匹配的是:一个空格,然后是一些非空格字符,然后一个空格。它会把匹配到的整个部分(包括空格替换为` 新内容 `(注意,这里我们替换的时候保留了空格,但中间的内容变成了“新内容”)。但是,注意,这个模式会匹配单个空格分隔的单词,例如"a b c"中的每一个单词都会被匹配(因为每个单词前后都有一个空格),但这样会匹配整个字符串,导致多次替换,而且可能不是用户想要的。 用户要求的是“两个空格之间”,那么两个空格之间意味着前后都是两个空格?还是前后各一个空格(加起来两个)?实际上,两个空格之间,通常是指两个连续的空格,但两个连续的空格之间是没有内容的(因为如果有内容,空格就被分开了)。所以,我们可能误解了用户的问题。 重新阅读引用[2]:“sed 替换连续空格”,用户可能更关心的是连续空格的处理。而引用[3]的例子中,替换的是空格和其后的一个任意字符,然后替换为两个空格(实际上是重复了匹配到的内容,即空格和那个字符,然后再加上一个空格?)。 考虑到用户的问题背景,以及引用[1]中提到的“替换shell脚本中的特殊字符”,我们猜测用户可能遇到了文本中有特殊字符,并且这些字符位于两个空格之间,需要替换。 但是,用户当前的问题很明确:“使用sed命令替换两个空格之间的内容”。因此,我们按照字面意思解决。 方案: 我们需要匹配的模式是:一个空格,然后一些内容(可能为空),然后一个空格。但是,这样会匹配单个空格分隔的单词,而且会重叠匹配(因为一个单词后面的空格也是下一个单词前面的空格)。 为了避免重叠,我们可以要求前面的空格是连续的两个,或者后面的空格是连续的两个?这样,我们就能够确定是“两个空格之间”的部分。 例如,我们可以这样定义:在两个连续空格之后,到下一个连续空格之前的内容。但这样定义比较复杂。 另一种理解:用户可能是指定界符为两个连续空格,然后替换其中的字段。例如,文本用两个空格作为分隔符,那么我们可以用awk来按两个空格分割,然后替换某个字段,再用两个空格连接。但用户要求用sed。 由于问题描述不够清晰,我们提供两种可能的解决方案: 1. 如果用户想要替换两个连续空格之间的内容(注意,两个连续空格之间实际上没有内容,因为空格是连续出现的,中间不可能有非空格字符),那么实际上就是替换连续空格本身。例如,将两个连续空格替换为一个空格,或者替换为其他字符串。但用户要求保留空格替换中间的内容,这中间的内容是空的,所以替换为空字符串?这没有意义。 2. 如果用户是指定界符为两个连续空格,那么两个连续空格之间的内容(即字段)可能包含非空格字符。例如,字符串"a hello world"(这里字段分隔是两个空格),那么第一个字段是"a",第二个字段是"hello",第三个是"world"。用户可能想替换第二个字段(即第一个两个空格和第二个两个空格之间的内容)为"hi",变成"a hi world"。 针对第二种情况,我们可以用sed这样实现: sed 's/ /@@@/g' # 先将两个空格替换成一个特殊的标记(比如@@@) sed 's/\(@@@\)[^@]*\(@@@\)/\1hi\2/g' # 但这样很麻烦,因为特殊标记可能出现在内容中 或者,我们可以用循环处理,但sed处理这种多次出现的情况比较复杂。 考虑到用户的问题,我们可能不需要这么复杂。实际上,如果字段分隔是两个空格,那么我们可以用: sed -E 's/( )[^ ]+( )/\1新内容\2/g' 这个命令的意思是:匹配两个空格(捕获为第一组),然后一个或多个非空格字符,然后再两个空格(捕获为第二组),然后替换为第一组的内容+新内容+第二组的内容。 但是,这个命令要求被替换的内容前后都是两个空格,而且被替换的内容是非空格字符(即不能包含空格)。所以,它只能替换两个空格之间且不包含空格的内容。 例如,字符串"a hello world"会被替换为"a 新内容 world"(注意,这里我们保留了前后的两个空格,只替换了中间的hello)。 但是,如果字符串是"a hello world"(注意,hello后面只有一个空格,然后world),那么就不会被匹配。 所以,这个命令适用于字段之间严格用两个空格分隔的情况。 如果用户想要替换的是任意两个空格之间的内容(即两个空格之间的任意字符串,可能包含空格),那么我们需要非贪婪匹配,但sed默认不支持。我们可以用其他方法,比如匹配任意字符,但直到遇到两个连续空格为止。这很难用基本正则表达。 因此,我们提供以下两种场景的解决方案: 场景一:替换两个连续空格之间的非空格字符串(即字段内容,且字段内不含空格)。 命令:`sed -E 's/( )[^ ]+( )/\1新内容\2/g'` 场景二:替换两个空格之间的内容(可能包含空格),但要求这两个空格是字段分隔符(即字段之间用两个或以上空格分隔,且我们要替换一个字段,这个字段可能包含空格?)。这种情况很少见,因为字段分隔符是空格,字段内通常不会包含空格。如果字段内包含空格,那么用空格作为分隔符就不合适了。 鉴于问题描述不明确,我们提供场景一的解决方案,并假设用户想要替换的是两个连续空格之间的非空格字符串。 另外,如果用户只是想替换连续空格本身(比如将两个连续空格替换为一个空格),那么可以使用: sed 's/ / /g' 或者,将两个以上连续空格替换为一个空格: sed 's/ \+/ /g' 但用户要求的是替换两个空格之间的内容,所以我们还是按照场景一处理。 示例: 输入: "apple banana cherry" 命令: sed -E 's/( )[^ ]+( )/\1fruit\2/g' 输出: "apple fruit cherry" 注意:banana被替换为fruit,因为它前后都有两个空格。 但是,如果输入是"apple banana cherry"(banana后面只有一个空格),则不会被替换。 如果用户想要替换任意位置的两个空格之间的内容(即只要前后各有一个空格,不管是否连续),那么我们可以这样: sed -E 's/ ([^ ]*) / 新内容 /g' 但是,这个命令会替换单个空格之间的内容,而且会重叠匹配。例如,输入"a b c"会变成"a 新内容 c",但注意,它匹配了" b ",替换后,原来的两个空格变成了一个空格(因为替换字符串中我们只写了一个空格),而且只替换了第一个匹配项(如果使用g标志,则会匹配所有,但注意,匹配会重叠吗?实际上,匹配不会重叠,因为空格被消耗了。例如: echo "a b c" | sed -E 's/ ([^ ]*) / 新内容 /g' 输出:a新内容c (因为匹配了" b ",替换为"新内容",注意替换后的字符串前后各有一个空格,但这里我们写的是“新内容”前后各一个空格,所以整个字符串变成"a新内容c") 但是,这个命令将每个单个空格之间的内容都替换了,而且改变了空格的数量(替换后,每个字段之间变成了一个空格)。 因此,我们回到用户的问题:替换两个空格之间的内容。我们假设用户指的是两个连续空格作为分隔符,并且要替换它们之间的字段(字段内不含空格)。 所以,我们推荐使用: sed -E 's/( )[^ ]+( )/\1新内容\2/g' 注意:这个命令要求被替换的字段前后都有两个空格,且字段内不包含空格。 如果用户的情况不同,可以根据实际调整。 另外,如果用户想要替换的字段内可能包含空格,那么建议使用awk,按两个连续空格作为分隔符,然后替换特定字段,再用两个空格连接。 例如,用awk实现替换第二个字段: awk -F ' ' '{OFS=" "; $2="新内容"; print}' # 注意,这里FS是两个空格,OFS也是两个空格 但用户要求用sed,所以这里只提供参考。 总结: 我们使用sed的扩展正则表达式模式(-E),并利用捕获组来保留两个空格替换中间的非空格内容。 命令: sed -E 's/( )[^ ]+( )/\1新内容\2/g' 注意:这个命令在macOS的sed上可能不兼容,因为macOS的sed使用-E选项(同Linux),但有些旧版本可能用-r。如果遇到问题,可以尝试用-r(GNU sed)或者不使用扩展模式(用基本正则,需要加更多的反斜杠)。 基本正则写法: sed 's/\( \)[^ ]\+\( \)/\1新内容\2/g' 其中,`\+`表示匹配一次或多次(在基本正则中需要转义为`\+`),而`\( \)`表示捕获组。 如果字段内容可能为空(即两个连续空格紧挨着),那么我们需要将`[^ ]\+`改为`[^ ]*`(匹配0次或多次),即: sed -E 's/( )[^ ]*( )/\1新内容\2/g' 或基本正则: sed 's/\( \)[^ ]*\( \)/\1新内容\2/g' 这样,如果遇到两个连续空格紧接着两个连续空格(如"a b"),那么会匹配第一个两个空格和接下来的两个空格之间的空字符串,然后替换为"新内容",结果变成"a 新内容 b"(注意,这里a和b之间原本是四个空格,被替换后变成了两个空格+新内容+两个空格,所以a和b之间现在有"新内容"和四个空格?实际上,匹配是从第一个两个空格开始,然后匹配0个或多个非空格字符(这里匹配0个),然后匹配接下来的两个空格。所以匹配的是前两个空格和紧接着的两个空格(四个空格的前两个和后两个),然后替换为:第一个捕获组(即前两个空格)+"新内容"+第二个捕获组(后两个空格),所以结果变成:a + 两个空格 + "新内容" + 两个空格 + b。这样就在原本四个空格的位置插入了“新内容”,而空格数量不变。 所以,这个命令也可以处理两个连续空格之间没有内容的情况(即两个连续空格后面紧跟着两个连续空格,中间没有非空格字符)。 但是,如果文本中只有一个地方有两个连续空格,而其他地方没有,那么可能匹配不到。 因此,我们给出最终建议: 命令:`sed -E 's/( )[^ ]*( )/\1新内容\2/g'` 这个命令会替换所有被两个连续空格包围的内容(包括空内容)为“新内容”。 示例: 输入: "apple cherry" (四个空格) 第一次匹配:前两个空格作为第一组,然后匹配0个非空格字符(因为紧接着又是两个空格,所以匹配第二组),然后替换为:两个空格+"新内容"+两个空格,所以输出:"apple 新内容 cherry" 注意:这样替换后,apple和cherry之间仍然是四个空格,但中间插入了“新内容”。 如果用户希望删除两个连续空格之间的内容(即替换为空字符串),那么可以将命令改为: sed -E 's/( )[^ ]*( )/\1\2/g' 这样,两个空格之间的内容被移除,但保留了两个空格。但这样实际上两个空格合并了?因为第一组是两个空格,第二组也是两个空格,所以结果是四个空格?所以,如果原本是四个空格,那么替换后还是四个空格,但中间没有内容(即四个空格连在一起)。如果原本是"apple banana cherry",替换后变成"apple cherry"(四个空格)。 所以,根据用户需求,替换内容可以自行定义。 最后,注意:如果一行中有多个这样的结构,由于使用了g标志,会全部替换。 如果用户的需求不同,请根据实际情况调整。 由于问题描述不够精确,我们提供了最可能的解决方案。如果用户有进一步说明,可以调整。</think>在 `sed` 中替换两个空格之间的内容,核心是**匹配两个空格之间的字符序列并保留空格本身**。以下是详细方法和示例: --- ### 一、基础替换方法 #### 1. **替换两个空格之间的非空格内容** ```bash # 替换两个连续空格之间的非空格字符(如 "a banana c" → "a FRUIT c") echo "a banana c" | sed -E 's/( )[^ ]+( )/\1FRUIT\2/g' ``` - **解析**: - `( )`:捕获第一个空格组(保留) - `[^ ]+`:匹配**非空格字符**(需替换的内容) - `( )`:捕获第二个空格组(保留) - `\1FRUIT\2`:替换为"第一个空格 + FRUIT + 第二个空格" #### 2. **替换包含空格的内容(需明确边界)** ```bash # 若内容含空格(如 "a hello world c"),需指定边界(例如引号) echo 'text "old content" end' | sed -E 's/( ")[^"]+(" )/\1NEW CONTENT\2/g' ``` - 输出:`text "NEW CONTENT" end` --- ### 二、处理连续空格(引用[2]补充) 若输入含连续空格(如 `a b`),需区分两种场景: ```bash # 场景1:替换两个空格之间的空内容(如 "a b" → "a TEXT b") echo "a b" | sed -E 's/( ) ( )/\1TEXT\2/g' # 匹配4个空格中的中间两个 # 场景2:压缩连续空格(如 "a b" → "a b") echo "a b" | sed 's/ \+/ /g' # 引用[2]中连续空格处理 ``` --- ### 三、动态内容替换(脚本示例) 替换变量中的内容并保留空格: ```bash input="a banana c" new_text="ORANGE" echo "$input" | sed -E "s/( )[^ ]+( )/\1$new_text\2/g" ``` - **输出**:`a ORANGE c` --- ### 四、特殊字符处理(引用[1][3]补充) 若内容含特殊字符(如 `.`、`$`),需先转义: ```bash # 转义特殊字符后再替换 content="file.name" escaped=$(echo "$content" | sed 's/[\.]/\\&/g') # 转义点号 echo "a $content c" | sed -E "s/( )${escaped}( )/\1NEW\2/g" ``` - **输出**:`a NEW c` --- ### 五、注意事项 1. **空格数量**: - 严格匹配两个空格时用 ` `(两个空格) - 若空格数量不定,用 `[[:space:]]\{2,\}`(兼容制表符等) 2. **贪婪匹配**: - `[^ ]+` 避免跨多个字段(如 `a b c` 不会误匹配 `b c`) 3. **扩展正则**: - 使用 `-E`(GNU sed)或 `-r`(BSD sed)启用扩展正则 > **提示**:若内容含空格或结构复杂,建议先用 `awk -F ' '` 分割字段再处理[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值