用“-”替换行首的空格

Muf*_*ffy 5 sed text-processing

 wqdq
 wqdqgrhehr
 cnkzjncicoajc
 hello space
    oejwfoiwejfow
    wqodojw
    more spaces
    more
Run Code Online (Sandbox Code Playgroud)

这是我的文件,我想用sed

-wqdq
-wqdqgrhehr
-cnkzjncicoajc
-hello space
----oejwfoiwejfow
----wqodojw
----more spaces
----more
----
-
--
Run Code Online (Sandbox Code Playgroud)

我必须使用循环来制作它还是存在任何不同的方法?我试过这个:

user:~$ sed -n  '
: loop
  s/^ /-/
  s/[^-] /-/p
t loop' spaces
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 10

使用sed,您需要一个循环,例如:

sed -e :1 -e 's/^\( *\) /\1-/; t1' < file
Run Code Online (Sandbox Code Playgroud)

或者做类似的事情:

sed '
s/ */&\
/; # add a newline after the leading spaces
h; # save a copy on the hold space
y/ /-/; # replace *every* space with -
G; # append our saved copy
s/\n.*\n//; # remove the superflous part' < file
Run Code Online (Sandbox Code Playgroud)

使用perl,您可以执行以下操作:

perl -pe 's{^ *}{$& =~ y/ /-/r}e' < file
Run Code Online (Sandbox Code Playgroud)

或者

perl -pe 's/(^|\G) /-/g' < file
Run Code Online (Sandbox Code Playgroud)

\G在 PCRE 匹配中(宽度为零)在前一个匹配(在//g上下文中)的末尾。所以在这里,我们替换了行首^或前一个匹配的结尾之后的空格(即之前替换的空格)。

(那个也适用于sed支持 PCRE 之类的实现ssed -R)。

使用awk,您可以执行以下操作:

awk '
  match($0, /^ +/) {
    space = substr($0, 1, RLENGTH)
    gsub(" ", "-", space)
    $0 = space substr($0, RLENGTH+1)
  }
  {print}' < file
Run Code Online (Sandbox Code Playgroud)

如果您还想转换制表符(例如<space><tab>foo将转换为--------foo),您可以使用expand. 使用 GNU expand,您可以expand -i只转换行中前导空格中的制表符。您可以使用该选项指定制表位之间的距离(默认为每 8 列)-t

将其推广到所有水平间距字符,或者至少是[:blank:]您所在地区的类别中的那些字符,这会变得更加复杂。

如果不是 TAB 字符,它只是一个问题:

perl -Mopen=locale -MText::CharWidth=mbswidth -pe 's/^\h+/"-" x mbswidth($&)/e'
Run Code Online (Sandbox Code Playgroud)

但TAB字符是控制字符具有的宽度-1mbswidth(),而实际上它具有取决于它在的行中发现1至8列的可变宽度。

expand命令负责将其扩展到正确数量的空格,但是expand当存在多字节字符(如除制表符之外的所有空白字符,UTF-8 语言环境中的空格)时,包括 GNU 在内的几种实现都无法正确执行,甚至一些支持多字节字符的字符也可能被零宽度或双宽度字符所迷惑(例如 U+3000[:blank:]至少在典型的 GNU 语言环境中属于此类)。因此,必须手动进行 TAB 扩展,例如:

perl -Mopen=locale -MText::CharWidth=mbswidth -pe 's{^\h+}{
  $s = $&;
  while ($s =~ /(.*?)\t(.*)/) {
    $s = $1 . (" " x ((7-mbswidth($1)) % 8 + 1)) . $2;
  }
  "-" x mbswidth($s)}e'
Run Code Online (Sandbox Code Playgroud)