如何删除文件中每行最后一个字符之前的字符?
我尝试sed 's/.$//' myfile1.txt
删除每行的最后一个字符myfile1.txt
,但我不确定如何删除每行的倒数第二个字符。
答案1
你可以做:
sed -E 's/.(.)$/\1/' file.txt
要就地编辑文件而不进行备份:
sed -Ei 's/.(.)$/\1/' file.txt
要就地编辑文件,并使用.bak
扩展名备份原始文件:
sed -Ei.bak 's/.(.)$/\1/' file.txt
POSIX 风格:
sed 's/.\(.\)$/\1/' file.txt
答案2
完整解释可移植命令(既然有人问了)这样任何人都可以理解这一点:
sed 's/.\(.\)$/\1/' file.txt
首先,“显而易见”:这一行包含一个命令名称 ( sed
) 和两个由 shell 传递给该命令的单独参数。单引号被 shell 去掉,所以sed
“看到”的参数是:
s/.\(.\)$/\1/
和
file.txt
由于没有任何参数以sed
连字符开头,因此它不会将它们解释为选项。
第一个参数被解释为要运行的编辑命令,任何其他参数(在本例中只是一个,file.txt
)被解释为从中读取要由编辑命令编辑的文本的文件的名称(第一个参数) 。
(请注意,编辑后的文本将写入sed
“标准输出”,即返回到终端、命令行窗口,而不是写回文件。)
file.txt
必须是执行此命令时位于 shell 的“当前工作目录”目录中的文件的文件名sed
。 (如果您希望命令在同一文件上运行,无论运行该命令时 shell 的当前工作目录是什么,请阅读“绝对路径”。)
现在我们将解构编辑命令本身:
s/.\(.\)$/\1/
编辑命令以字母 开头s
,代表“替换”。从“s”后面的字符(/
在本例中)到该同一字符的下一个实例(/
再次),是图案是要被替换的。换句话说,它指定要被替换的文本应该“看起来像什么”——它告诉sed
如何“知道”何时找到了应该被替换(应该被替换)的文本。
本例中的模式是:
.\(.\)$
(代替“模式”的正确术语实际上是正则表达式,最初是“正则表达式”的缩写。我不会在这里讨论更广泛的正则表达式主题。)
该正则表达式以点 ( .
) 开头,它是一个“通配符”,含义为“任何单个字符”。它火柴(描述、象征)文本的任何单个字符。
反斜杠 ( \
) 经常在 shell 命令和正则表达式中用作“转义”字符。一般来说,这意味着要么删除它后面的字符的特殊意义,或者它添加对于以下字符具有特殊意义。
在这种情况下,括号(和(
))
是逃脱了(也就是说,前面有一个反斜杠)为了添加有特殊的意义。正则表达式中转义括号的特殊含义sed
是,任何与括号之间的正则表达式部分匹配的文本都会被特别“注释”,并且可以转回到。我们稍后会再讨论这一点(当我们回顾这个括号分组时)。
.
括号内的句点 ( ) 再次匹配任何单个字符。
美元符号 ( $
) 称为锚,它匹配一行文本的末尾。 如果没有这个锚点,正则表达式将简单地匹配任意两个字符(具体来说,它将匹配从名为 的文件中读取的每行文本的前两个字符file.txt
),并且(由于转义括号)sed
将“注释”这两个字符中的第二个字符,以便稍后引用。
因为正则表达式是锚定的到行尾,两个点必须匹配最后的每行文本上有两个字符(最后一个字符会被注明以供稍后参考)。
(替换)命令的下一部分s
是从后面的字符的第二个实例s
(在本例中是斜杠,/
)到后面的字符的第三个实例s
。这被称为替换模式。 它指定了sed
应该做什么代替匹配的文本搜索模式(正则表达式)。
在这种情况下,替换模式是:
\1
同样,反斜杠用于逃脱接下来的字符,在这种情况下又是添加具有特殊意义,而不是消除特殊意义。
反斜杠后跟数字(从 1 到 9)称为反向引用。 这是什么回指搜索模式中括号内匹配的文本分组。由于数字是1
,这指的是第一的括号分组。 (当然,在这种情况下,只有一个这样的分组。)
总而言之,这个编辑命令的意思是使用那些转义括号(即该行的最后一个字符)内匹配的文本来替换由转义括号匹配的文本。全部的搜索正则表达式(这是最终的二该行的字符)。
最终效果是从每行中删除倒数第二个字符。
或者,更准确地说,将从当前工作目录中sed
名为 find 的文件中读取每一行文本;file.txt
对于每一行,它将替换最后一行二该行的字符以及该行的单个最终字符;它会将每个修改的行打印到其标准输出。