在Unix

时间:2018-04-08 02:38:57

标签: shell

每次在Unix中有两个空格的空间时,我都会尝试替换。我们只是从标准输入读取并写入标准输出。我还必须避免使用函数awk和perl。例如,如果我读到类似San Diego的内容,则应该打印San Diego。如果已经有多个空格,那就应该让它们独自存在。

4 个答案:

答案 0 :(得分:1)

仅限bash怎么样?首先测试file

$ cat file
 1
  2 3
    4  5
San Diego  NO

然后:

$ cat file | 
while IFS= read line
do 
  while [[ "$line" =~ (^|.+[^ ])\ ([^ ].*) ]]
  do 
    line="${BASH_REMATCH[1]}  ${BASH_REMATCH[2]}"
  done
  echo "$line"
done
  1
  2  3
    4  5
San  Diego  NO

答案 1 :(得分:1)

你必须要小心,不要忘记开头或结尾的空格。 我提出了三个用于教育目的的解决方案:

sed 's/\(^\|[^ ]\) \($\|[^ ]\)/\1  \2/g'    # solution 1
sed 's/\( \+\)/ \1/g;s/ \(  \+\)/\1/g'      # solution 2
sed 's/ \( \+\)/\1/g;s/\( \+\)/ \1/g'       # solution 3    

所有三种解决方案都使用子表达式:

  

<强> 9.3.6 BREs Matching Multiple Characters

     

子表达式可以通过将其包含在BRE中来定义   字符对\(\)。这样的子表达式应该匹配   没有\(\)的任何匹配,除此之外   在子表达式内锚定是可选行为;见BRE Expression Anchoring。 Subexpressions可以任意嵌套。

     

反向引用表达式'\n'应匹配相同(可能   空的)字符串,由附带的子表达式匹配   在\(之前的“\)”和“'\n'”之间。角色n应为a   从19的数字,指定第n个子表达式(表示第n个子表达式)   从模式开始的第n \(开始并结束   与相应的配对\))。如果表达式无效   在n之前小于\n个子表达式。例如,   表达式“.∗\1$”匹配由两个相邻的行组成的行   同一个字符串的出现,表达式a*\1失败   匹配a。当引用的子表达式匹配多个时   string,后引用的表达式应引用最后匹配的表达式   串。如果反向引用引用的子表达式匹配   由于星号(*)或间隔而导致多个字符串   表达式(见第(5)项),后引用应与最后一个匹配   (最右边)这些字符串。

解决方案1:sed 's/\(^\|[^ ]\) \($\|[^ ]\)/\1 \2/g'

这里有两个子表达式。第一个子表达式\(^\|[^ ]\)匹配行的开头(^)或(\|)非空格字符([^ ])。第二个子表达式\($\|[^ ]\)类似,但行尾($)。

解决方案2:sed 's/\( \+\)/ \1/g;s/ \( \+\)/\1/g'

用一定数量的空格和一个空格替换一个或多个空格。然后我们通过从那些空间中移除一个空格来校正具有3个或更多空格的那些。

解决方案3:sed 's/ \( \+\)/\1/g;s/\( \+\)/ \1/g'

这与解决方案2完全相同,但反转了逻辑。首先从具有多个空格的所有序列中删除空格,然后添加空格。这个单行只比解决方案2短一个字符。

示例:基于解决方案1 ​​

以下命令不仅仅是echo "string" | sed ...,而是显示空格,包含在printf语句中。

# default string
$ printf "|%s|" " foo bar  car "
| foo bar  car |
# spaces replaced
$ printf "|%s|" "$(echo " foo bar  car " | sed 's/\(^\|[^ ]\) \($\|[^ ]\)/\1  \2/g')"
|  foo  bar  car  |
# 3 spaces in front and back
$ printf "|%s|" "$(echo "   foo bar  car   " | sed 's/\(^\|[^ ]\) \($\|[^ ]\)/\1  \2/g')"
|   foo  bar  car   |

注意:如果您想用相同的双色空格替换任何形式的空白(任何编码中的空格和制表符),您可以使用:

sed 's/\(^\|[^[:blank:]]\)\([[:blank:]]\)\($\|[^[:blank:]]\)/\1\2\2\3/g'
sed 's/\(^\|[[:graph:]]\)\([[:blank:]]\)\($\|[[:graph:]]\)/\1\2\2\3/g

答案 2 :(得分:0)

的内容
cat input.txt | sed 's,\([[:alnum:]]\) \([[:alnum:]]\),\1  \2,'

应该为此目的而工作。

答案 3 :(得分:0)

仅替换2个字符之间出现1个空格的帽子不是带有2个空格的空格

  `sed 's/\([^ ]\) \([^ ]\)/\1  \2/g' file`

1) [^ ] - 不是空格字符

2) \1 \2 - 在括号中找到的第一个表达式,2个空格,第二个括号到期

3)一起使用的

s///g sed将第一个//中的正则表达式替换为第二个//中的值