【问题标题】:Trim space ONLY from start & end of document without touching internal space using perl in shell script仅从文档的开头和结尾修剪空间,而不使用 shell 脚本中的 perl 触及内部空间
【发布时间】:2021-09-22 07:43:50
【问题描述】:

我正在尝试在 bash 脚本中使用 perl 来修剪文档开头和结尾处的空间,而不触及文件中的中间空间

文件格式如下

<newline>
<space><newline>
<tab><newline>
<space><tab><newline>
START<newline><newline>
<space>INDENTED<newline><newline>
END<newline>
<space><tab><newline>
<tab><newline>
<space><newline>
<newline>

注意:&lt;newline&gt;\n&lt;space&gt; & &lt;tab&gt;\t

原来的文件是这样的


  
    
    
START


 INDENTED


END

    
    
 


我需要文件的内容是

START<newline><newline>
<space>INDENTED<newline><newline>
END

即像这样的最终文件

START


 INDENTED


END

我尝试使用以下命令同时使用它们,但它也会修剪中间空间。它们都从整个文档中修剪空格和换行符,而不仅仅是从文档的开头开始

perl -pi -e 's/^\s*//gs' sample.txt
perl -pi -e 's/\A\s*//gs' sample.txt

两者都折叠了所有内部空间

START<newline>
INDENTED<newline>
END<newline>

我试过这个。它折叠了换行符

perl -pi -e 's/\s*$//gs' sample.txt
perl -pi -e 's/\s*\Z//gs' sample.txt

两个折叠的换行符

START<space>INDENTEDEND<newline>

这是我的假设

  1. \A 仅匹配文档的开头,\Z 匹配文档的结尾(而不是 ^$
  2. gs 标志中的 s 确保整个文档被视为单行,换行符替换为字符 \n

我是 perl 的新手。感谢有人可以帮助我了解我哪里出错了

【问题讨论】:

  • @choroba 在我在这里发布问题后,我不确定它是否属于这里/服务器故障论坛。所以,我也在那里发布了同样的问题。你知道哪个论坛是对的吗?
  • @mpapec 对于perl -i -pe 's/^\s+|\s+$//g' sample.txt,我知道了STARTINDENTEDEND
  • 它甚至可能同时适用于两者,但并非没有将它们相互关联。没有链接意味着没有同时访问这两个站点的人可能会将精力浪费在其他地方已经解决的问题上。

标签: perl


【解决方案1】:

您可以在slurp 模式下使用这个perl

perl -0777 -pe 's/^\s+|\R?\K\s+$//g' file

输出:

START

 INDENTED

END

详情:

  • -0777 启用 slurp 模式以使 perl 读取完整文件
  • ^\s+ 匹配文件开头的 1+ 个空格
  • \R?\K\s+$: 匹配一个换行符,最后是 1+ 个空格。使用\K,我们在\R 之后重置匹配,这样就不会删除结束换行符

【讨论】:

  • 谢谢。我认为啜饮模式是我正在寻找的。如果我不使用就地模式,它就可以工作。 slurp 模式是否不适用于就地 -i 标志?我试过perl -0777 -pe -i 's/^\s+|(\R)\s+$/$1/g' sample.txt。它不会就地替换。只需将输出重定向到 shell。有什么想法吗?
  • 即使这与您在不捕获和替换 perl -0777 -pe 's/^\s*|\s*$//g' file 的情况下指定的内容完全相同。任何想法 w.r.t inplace 东西?
  • perl -0777 -pe 's/^\s*|\s*$//g' 将删除END 之后的换行符,这显然是你不想要的。
  • 为了避免 $1 使用:perl -0777 -pe 's/^\s+|\R\K\s+$//g' file
  • 我也是 Java 人,\K 仅在 PCRE 中受支持。我把它作为答案的一部分,因为我们在这里使用perl。否则对于 Java 类型的正则表达式,我们应该使用 's/^\s+|(\R)\s+$/$1/g' file
【解决方案2】:

不是perl,而是ed 对编辑文件很有用:

$ printf '%s\n' '1,/START/-1d' '/END/+1,$d' w | ed -s sample.txt
$ cat sample.txt
START

 INDENTED

END

d删除从第一行到匹配START的行之前的行以及从END之后的行到文件末尾的行范围内的所有内容,然后w将更改的文件写入磁盘。


或类似的perl 方法,它只打印您想要保留的范围内的行:

perl -i -ne 'print if /START/../END/' sample.txt

【讨论】:

  • 谢谢。但我喜欢正则表达式并使用我编码的每种语言。ed 有自己的工具特定的东西(语言?/标志)我需要了解。
  • @AshokKoyi 里面有两个正则表达式。 (虽然ed 使用 POSIX 基本正则表达式(并且某些版本也可以使用扩展 RE),而不是 perl 样式的。)
  • @AshokKoyi 添加了 perl 单行。
  • 两个正则表达式可以交替使用并替换为一个。其他人分享了这个s/^\s+|(\R)\s+$/$1/g。这是一个很好的技巧,可以保留最后一个换行符
【解决方案3】:

这是一个简短的 sed 版本:

sed -n '/START/,/END/p'

或者用否定逻辑:

sed '1,/START/{/START/!d}; /END/,${/END/!d}'

【讨论】:

    猜你喜欢
    • 2013-04-13
    • 2011-03-01
    • 2023-04-09
    • 2023-03-04
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    相关资源
    最近更新 更多