如何使用 sed 检测行尾

如何使用 sed 检测行尾

我正在寻找一种仅在最后一个字符是换行符时才执行替换的方法,使用sed.

例如:

lettersAtEndOfLine

被替换,但这不是:

lettersWithCharacterAfter&

由于sed不能很好地处理换行符,因此它并不像

$ sed -E "s/[a-zA-Z]*\n/replace/" file.txt

如何才能做到这一点?

答案1

有了标准sed,你就会绝不在从文件读取的文本中看到换行符。这是因为逐行读取,因此在的模式空间sed中当前行的文本末尾没有换行符。sed换句话说,sed读取换行符分隔的数据,并且分隔符不是sed脚本所看到的内容的一部分。

正则表达式可以是锚定的在行尾使用$(或在行首使用^)。将表达式锚定在行的开头/结尾处会强制它在此处完全匹配,而不是仅在行上的任何位置匹配。

[A-Za-z]*如果您想用某些内容替换行末尾与模式匹配的任何内容,请像这样锚定模式:

[A-Za-z]*$

...将强制它在行尾匹配,而不是在其他地方匹配。

然而,因为[A-Za-z]*$也匹配没有什么(例如,末尾出现的空字符串每一个行),你需要强制匹配某物,例如通过指定

[A-Za-z][A-Za-z]*$

或者

[A-Za-z]\{1,\}$

所以,你的sed命令行将是

$ sed 's/[A-Za-z]\{1,\}$/replace/' file.txt

我在这里没有使用非标准-E选项,因为它不是严格需要的。有了它,你就可以写出

$ sed -E 's/[A-Za-z]+$/replace/' file.txt

这是一个品味问题。

答案2

sed "s/[a-zA-Z]*$/replace/" input.txt > result.txt

或者,漫长而复杂的不必要的方式:

我发现,这可以完成,仍然使用 sed,在 tr 的帮助下。您可以指定另一个字符来表示行尾。必须使用另一个临时字符,在本例中为“`”。我们用“~”来表示行尾:

tr '\n' '`' <input.txt >output.txt
sed -i "s/`/~`/" output.txt
tr '`' '\n' <output.txt >result.txt

然后要执行实际的搜索和替换,请使用“~”而不是“\n”:

sed -i -E "s/[a-zA-Z]*~/replace/" result.txt

然后清理其他行上多余的字符:

sed -i "s/~//" result.txt

显然,这一切都可以通过管道连接在一起,从而产生如下结果:

tr '\n' '`' <input.txt | sed -e "s/`/~`/" | tr '`' '\n' | sed -E -e "s/[a-zA-Z]*~/replace/" | sed "s/~//" > result.txt

答案3

从您发布的(损坏的)代码片段来看,您似乎也想替换换行符。在这种情况下,正则表达式锚定本身无法帮助您。下面是一个解决方案:

sed '/[[:alpha:]]\+$/{N;s/[[:alpha:]]\+\n/replace/}' your_file

细分:

  • /[a-zA-Z]\+$/{}意味着将花括号内的任何内容应用于与正则表达式匹配的行。
  • 正则表达式是使用锚定的正则表达式,如下所示你自己的答案,修改为取格伦·杰克曼的评论考虑到。
  • 在花括号内,N表示“将下一行附加到活动缓冲区”(sed称为“模式空间”)
  • 最后,该s///语句是您所需的替换。它现在可以工作,因为模式空间包含两个连续的行,因此换行符是其中的一部分。

答案4

要找到行尾,只需使用$符号:

没有行尾锚点:

sed -n '/pattern/p' file 

使用行尾锚点:

sed -n '/pattern$/p' file

相关内容