Board logo

标题: 如何显示文件的最后一行? [打印本页]

作者: wingofsea     时间: 2006-5-24 15:22    标题: 如何显示文件的最后一行?

如何写batch文件或者使用dos命令显示 文件的最后一行?
如:
showLastLine.bat samle.txt

"this is the last line of sample file."
作者: vvillsort     时间: 2006-5-24 16:43
@echo off
set a=0
for /f %%a in (你要搜索的文件.txt) do set a=%%a
echo %a%
作者: 3742668     时间: 2006-5-24 19:04
灌个水,楼上的你是willsort兄的fans?
作者: Scott0902     时间: 2006-5-24 22:52
vvillsort 莫非是 willsort 的马甲?
作者: willsort     时间: 2006-5-24 23:44
Re vvillsort:

      你的代码思路我认同,只是增补一些细节。但即使如此,它仍然无法处理一些特殊的情况,比如当最后一行为空行时,比如此行含有某些“>|<”之类的特殊字符时。

      如果楼主没有严格的需要,你的代码应该足够了。但是,我们可以将如何禁止for忽略空行以及如何实现原文echo作为研究题目,提高我们的水平,增加代码的质量。
@echo off & setlocal
set a=
for /f "delims=" %%a in (sample.txt) do set a=%%a
echo.%a%

作者: vvillsort     时间: 2006-5-25 08:41
YES,三楼和四楼回答正确,我就是willsort传说中的粉丝 .......................哈哈哈
作者: Climbing     时间: 2006-5-25 10:00
楼主没有限定不使用第三方工具,所以如果用sed来实现会更简单。

sed -ne "$p" sample.txt

"$p"表示打印最后一行,-n表示不显示其它内容,-e表示执行后面的脚本。
作者: jawbin     时间: 2006-5-25 11:35
晕倒....
作者: wingofsea     时间: 2006-5-25 14:20
谢谢大家,学到了很多东西,多谢:)最近要写一些脚本,发现自己对这块还特别不了解,学习中。。。再次感谢
作者: Climbing     时间: 2006-5-25 16:33


  Quote:
Originally posted by jawbin at 2006-5-25 11:35:
晕倒....

你晕倒什么?
作者: willsort     时间: 2006-5-25 16:43
Re Climbing:

      wingofsea 在顶楼已提出“写batch文件或者使用dos命令”,除非兄认为第三方工具也属于DOS命令。当然,你的回复很有用,不仅楼主受益,我也进一步巩固了sed的脚本基础。对兄表示感谢!
作者: Climbing     时间: 2006-5-25 19:03
Re wil兄:

哈哈,我一向认为凡是能在dos下运行的命令就是dos命令,非局限于只有微软提供的DOS命令。我的原则就是:甭管黑猫白猫,能抓老鼠就是好猫。技术穷根究底固然重要,非唯此而不精,但在工作上则是以解决问题为第一要务。

以兄的水平,sed的这点儿小猫腻对你实在是太简单了,我是班门弄斧,见笑见笑。你说话现在水平越来越高了,到底有多高,怎么也得有十层楼那么高~~~~
作者: 3742668     时间: 2006-5-25 19:12
如果只是纯粹地显示最后一行的话,这样几条命令无疑是效率高,容错好的:
@echo off
type %1
for /l %%i in (1,1,24) do echo.
pause>nul
其中的24表示屏幕的高度-1。
    个人认为在处理文本内容方面,用VBS要比BAT合适得多。
作者: fan927     时间: 2006-5-25 19:34


  Quote:
Originally posted by Climbing at 2006-5-25 10:00:
楼主没有限定不使用第三方工具,所以如果用sed来实现会更简单。

sed -ne "$p" sample.txt

"$p"表示打印最后一行,-n表示不显示其它内宠...

Climbing大侠,
这条命令如果遇到以空格的结尾是无效的,需要这么写:
sed "/^$/d" sample.txt|sed -ne "$p"
其中,要先用 " /^$/d"  过虑一下空行,让后再执行你这条命令.
班门弄斧了.
作者: Climbing     时间: 2006-5-25 22:13
Re fan927:

多谢指正,只不过楼主要求显示最后一行,并没有说要过滤空行,当然,空行也算是最后一行,我是这么理解的,嘿嘿~~~

而且,似乎用你的方法也只能过滤空行,如果一行中有若干空格也是无法过滤的,所以,似乎这样更为妥当:
sed "/^ *$/d" sample.txt | sed -ne "$p"
作者: fan927     时间: 2006-5-26 06:26
说的也是,请教一下,这个*是什么作用吗?多谢Climbing兄.
作者: Climbing     时间: 2006-5-26 10:40
在正则表达式中,*表示前面字符从0个到若干个的重复,注意*前面还有一个空格。当然,严格追究,如果最后一行不是若干个ASCII的空格,而是汉字的全角空格或者是制表字符等,恐怕我那个命令也会失效,所以这就要具体情况具体分析了,必要时可以使用正则表达式中的字符集[xyz]来定义要过滤的字符。
sed "/^[ \t]*$" | ...

当然,我不知道上述写法是否正确,对于sed及正则表达式的了解我也只是一知半解。
作者: 无奈何     时间: 2006-5-26 23:34
To  Climbing
sed 可以用这样的方法过滤掉空行及空白行,而只显示含有有效字符的最后行。
sed -n "/^[ \t]*$/!h;${g;p}" file
作者: Climbing     时间: 2006-5-27 17:24
Re 无奈何:

请教一下“${g;p}”表示什么操作?
作者: 无奈何     时间: 2006-5-27 19:54
Re Climbing
这个例子中用到的函数解释如下:
        h 用模式空间的内容替换保留空间的内容。
        g 用保留空间的内容替换模式空间的内容。
        p 将模式空间写到标准输出。
前半部分代码的意思是,当当前行不匹配正则时就执行 h 命令,既保存当前行到保留空间。
${g;p} 的作用是当到达文件末尾时,替换模式空间的内容为此前保存到保留空间的内容,并输出。
作者: Climbing     时间: 2006-5-27 23:14
Re 无奈何:

学习了好长时间的sed的帮助,但一直还是搞不太明白sed的高级用法,例如楼上所说
的什么模式空间、保留空间等这些内容。看了你的解释,我更晕了。能不能系统的讲一下有关的概念?最好结合一些例子,看英文的说明,好多不知道什么意思。

有时候,我们经常用正则表达式来寻找一个有特定规律的字符串,然后将这个字符串替换为另一个(但替换后的内容包括查找的内容),例如查找由一串a组成的字符串(a的数量不定),假设找到后替换为原字符串加上一个数字5。我一直不知道如何用sed进行这样的操作。实际上这个问题就是后面的替换操作如何引用前面找到的字符串的问题。

例如:
查找:aaa      找到后替换为:aaa5
查找:aaaa     找到后替换为:aaaa5

希望无奈何兄在这方面再详细讲一下,谢谢!
作者: 无奈何     时间: 2006-5-28 00:47
Re Climbing
        说实在的我对 sed 的高级用法只是有所了解,根本不能自由运用。特别是 sed 模式空间(pattern space)、存储(或保留)空间(hold space)太过于抽象,同时还必须了解 sed 的处理机制和每个函数的执行流程。网上有很好的教程,你可以一点点学习,好多文章我读过 n+1 遍后仍不能很好掌握。
        关于字符串的匹配及获取,你需要了解正则表达式的应用。关于正则表达式的内容有些庞杂, unix 正则表达式有基本元字符集、扩展元字符集;还有大多数脚本语言使用的 perl 正则表达式。开始学习的时候有些困难,多看多用慢慢就会掌握的。简单的应用并不困难,当能自由运用时会发现手中的工具强大许多。
        你的问题实例
echo aaa |sed "s/\(a\{3\}\)/\15/"
echo aaa |sed -r "s/(a{3})/\15/"
可以看到 sed 在元字符集和扩展元字符集模式下不一样,给你提供一些网络链接,希望你早日掌握,有问题可以一起讨论。


正则表达式之道:http://dev.csdn.net/article/44/44550.shtm
正規表示式的入門與應用:http://www.rtfiber.com.tw/~changyj/
SED 手册:http://phi.sinica.edu.tw/aspac/reports/96/96005/
SED单行脚本快速参考:http://sed.sourceforge.net/sed1line_zh-CN.html
附件是 sed 很好的中文教程,忘了从哪本电子书上截取下来的了。其中关于 sed 的处理流程介绍的相当详细,缺点是不够生动。
附件 1: sed.pdf (2006-5-28 00:47, 575.44 K, 下载附件所需积分 1点 ,下载次数: 48)

作者: Climbing     时间: 2006-5-28 04:17
谢谢无奈何兄的推荐,基本上已经搞明白了sed的用法,你推荐的东西都相当的棒,只可惜,大部分是台湾同胞写的,习惯上较不同,还能接受。
作者: Climbing     时间: 2006-5-28 11:18
下面是我学习一晚上sed用法的汇报:

test.txt 内容如下:
ab
aa
aaba
b
AbA
bb
bbb
aaaa
cc
AAAA
cccc
aaaaaa
aaaaaab

要求:将test.txt上述字符串中凡是以a(无论大小写)连续的字符串后面加上一个5。

实现的命令:
sedw -ne "/\<[aA]*[aA]\>/s/\([aA]*\)/\15/p" test.txt

执行结果:

D:\work\dos\sed>sedw -ne "/\<[aA]*[aA]\>/s/\([aA]*\)/\15/p" test.txt
aa5
aaaa5
AAAA5
aaaaaa5

命令简单分析:
-n  不输出
-e  后跟脚本,可以有多个-e
/\<[aA]*[aA]\>/  表示查找以连续的a|A组成的字符串所在行, \<及\>定义字符串的开始和结尾
s/\([aA]*\)/\15/p  将连续的a|A字符串替换添加5。\(及\)将连续的a|A串定义为一个组,后面替换操作中用\1来引用这个组。
作者: willsort     时间: 2006-5-28 21:15
Re Climbing:

      兄实在高看我了,我只有站在大家筑成的十层楼顶,才会有十层楼的水平,否则一切只是虚幻的空中楼阁。

      sed脚本我远没有达到应用随心的地步,基本与兄相似,只有在用到sed脚本时,我才会专门学习与我应用相关的知识,属于半路出家的类型。

      对于grep/sed/awk这三大与正则表达式相关的字符流工具,我认为其处理能力上是依次增加的。grep只能过滤而无法编辑;sed则囿于仅能编辑模式,而awk则因为引入了类C的语法特征,具有了更丰富的处理能力。再加之我只有一定的C语言基础,而缺乏ed等工具的基本认知,所以对awk更加具有认同感,所以现在目前主要的学习方向是awk。

     再就兄24楼的例题略作补缀:

     1、首先,可以将行的查找与串的匹配合二为一,因为这对sed来说,都只是模式匹配。
sed -ne "s/\(\<[aA]*[aA]\>\)/\15/p" test.txt

     2、其次,就你的test.txt而言,全A词等同于全A行,所以可以用行首/行尾元字符进行匹配。
sed -ne "s/\(^[aA]*[aA]$\)/\15/p" test.txt

     3、再次,可以改用[aA]\+来隐含指定词尾为a/A,且至少含有一个a/A。
sed -ne "s/\(^[aA]\+$\)/\15/p" test.txt

[ Last edited by willsort on 2006-5-28 at 22:09 ]
作者: Climbing     时间: 2006-5-28 21:54
Re wil:

wil兄总是过谦了,你给出的三个答案随便拿一个出来都要比我的高明。可笑的是我竟然以为自己搞通了,惭愧惭愧。不过,还是有一点儿收获,我终于知道了\1, \2这种引用方式。