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