【问题标题】:How to replace leading whitespace with tabs using grep or sed?如何使用 grep 或 sed 用制表符替换前导空格?
【发布时间】:2016-05-02 22:53:36
【问题描述】:

我想使用 grep 或 sed 将文件中每一行的所有前导空白字符替换为相同数量的制表符。每行有几个空格,后跟一个破折号和一些文本。

 -Line 1  
  -Line 2  
   -Line 3

找到它们不是问题,但我不知道如何使用反向引用替换这些字符。比如:

sed 's/^([\s]+)(-.*)/\1\2/' file.txt

我该如何解决这个问题?还是有可能?

【问题讨论】:

  • 所以你想用相同数量的制表符替换所有空格字符?

标签: macos sed grep


【解决方案1】:

根据您的制表符宽度,您可能希望用制表符替换例如 4 或 8 个空格的块,例如

sed 's/^ \{4\}/\t/g' infile

sed 's/^ \{8\}/\t/g' infile

这会变成一个看起来像这样的文件

$ cat infile
no space
 1 space
  2 spaces
   3 spaces
    4 spaces
     5 spaces
      6 spaces
       7 spaces
        8 spaces
         9 spaces
          10 spaces
           11 spaces

进入这个(用^I 替换标签以便我们可以看到它们):

$ sed 's/^ \{4\}/\t/g' infile | cat -T
no space
 1 space
  2 spaces
   3 spaces
^I4 spaces
^I 5 spaces
^I  6 spaces
^I   7 spaces
^I^I8 spaces
^I^I 9 spaces
^I^I  10 spaces
^I^I   11 spaces

或者这个

$ sed 's/ \{8\}/\t/g' infile | cat -T
no space
 1 space
  2 spaces
   3 spaces
    4 spaces
     5 spaces
      6 spaces
       7 spaces
^I8 spaces
^I 9 spaces
^I  10 spaces
^I   11 spaces

标签宽度可以参数化(注意双引号):

$ tw=7
$ sed "s/ \{$tw\}/\t/g" infile | cat -T
no space
 1 space
  2 spaces
   3 spaces
    4 spaces
     5 spaces
      6 spaces
^I7 spaces
^I 8 spaces
^I  9 spaces
^I   10 spaces
^I    11 spaces

请注意如何在 vim 中轻松完成此操作,请参阅 this question

仅在行首有空格

上面的命令用制表符替换 any 四个或八个空格的组。如果你只想替换行首的空格,比如这样的文件:

$ cat infile 
    4 spaces    word
     5 spaces    word
      6 spaces    word
       7 spaces    word
        8 spaces    word 
         9 spaces    word

你可以使用

$ sed ':a;s/^\(\t*\) \{4\}/\1\t/;/^\t* \{4\}/ba' infile | cat -T
^I4 spaces    word
^I 5 spaces    word
^I  6 spaces    word
^I   7 spaces    word
^I^I8 spaces    word 
^I^I 9 spaces    word

这是做什么的:

# Label to branch to
:a

# Replace optional leading tabs followed by four spaces
# by the same amount plus one tabs
s/^\(\t*\) \{4\}/\1\t/

# If there are still four spaces after leading tabs, branch to a
/^\t* \{4\}/ba

更新

原来问题实际上是关于用制表符替换行首的空格。

对于这个输入

0 spaces
 1 space
  2 spaces
   3 spaces

以下 sed 命令有效:

$ sed ':a;s/^\(\t*\) /\1\t/;ta' infile | cat -T
0 spaces$
^I1 space$
^I^I2 spaces$
^I^I^I3 spaces$

解释:

:a                # Label to branch to
s/^\(\t*\) /\1\t/ # Capture tabs at start of line, replace next space with tab
ta                # Branches to :a if there was a substitution

【讨论】:

  • 感谢您的回答,但这并不能完全涵盖我的情况。我想用制表符替换开头的每个空格,而不是每 4 或 8 个空格。
  • @ganzpopp 我明白了 - 我已经添加了一个解决方案。
【解决方案2】:

保持简单,只需使用 awk:

$ awk '{s=$0; sub(/[^ ].*/,"",s); gsub(/ /,"\t",s); sub(/^ +/,s)} 1' file
        -Line 1
                -Line 2
                        -Line 3

【讨论】:

    猜你喜欢
    • 2012-03-02
    • 2015-11-01
    • 1970-01-01
    • 2014-02-04
    • 2019-06-07
    • 1970-01-01
    • 2014-01-13
    • 2018-02-24
    • 2015-11-21
    相关资源
    最近更新 更多