LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 800|回复: 6

有人修改过less吗?

[复制链接]
发表于 2010-8-31 15:57:59 | 显示全部楼层 |阅读模式
虽然据说让less一直显示行号会让速度变慢, 但是我还是想在每行前面有个行号. 用"less -N"可以达到这个效果,但是它的行号显示比较别扭,不支持彩色也就罢了,貌似在最前面还有个"\t". 这样原本比较紧凑的文本就会在最前面空出一大块来. 我没找到有什么办法可以改变这一点,就想到了改源码. 但是从gnu下载了源码后, 我很悲剧地发现一下子找不到这个"\t"是在哪个文件的什么地方加上去的.

请问这里有人修改过less源码吗?是否可以指点一二?
发表于 2010-8-31 17:01:43 | 显示全部楼层
如果不要前面的\t并且行号是彩色的话,可以这样:
编辑/usr/local/bin/myless,内容为:
#!/bin/bash
cat -n "$@"|awk  '{ printf "\x1b[34;01m%s \x1b[39;49;00m",$1; for (i=2; i<=NF; i++) printf "%s ", $i; printf "\n"; }' |less

然后chmod +x /usr/local/bin/myless
可以像less一样使用,例如:
genlopt -l|myless

\x1b[34;01m代表蓝色,你可以用别的颜色代码替换
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-8-31 17:33:11 | 显示全部楼层
Post by pheyx;2110549
如果不要前面的\t并且行号是彩色的话,可以这样:
编辑/usr/local/bin/myless,内容为:
#!/bin/bash
cat -n "$@"|awk  '{ printf "\x1b[34;01m%s \x1b[39;49;00m",$1; for (i=2; i<=NF; i++) printf "%s ", $i; printf "\n"; }' |less

然后chmod +x /usr/local/bin/myless
可以像less一样使用,例如:
genlopt -l|myless

\x1b[34;01m代表蓝色,你可以用别的颜色代码替换


非常感谢!
但是这段我不是很明白. 你前面用awk定义了各种色彩,但是管道最后是个less,也就是说最终还是less来显示的, 那么之前的色彩又如何被识别呢?

我测试了一下,验证了我的疑问,把最后面的"|less"去掉的话,颜色也有,行号也有,只不过是类似于cat的一下子打印出了所有内容;加上最后的"|less"的话,内容是以less的方式显现的,但是那些字符并没有被识别出来,而是在正文前生成了"ESC[34;01m45 SC[39;49;00m"这么一串.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-8-31 17:41:12 | 显示全部楼层
我突然想到了一件事! 你是不是alias了 less = less -R ? 我把"|less" 改成 "|less -R" 后,就一切正常了.

现在就剩下一个遗憾了.less原本的方式会造成一大块空白,但是并不是简单的"\t",而是连同行号在内,占据一段固定长度. 刚刚我在源码中也找到了关于这个的地方. 在 line.c里面,原文是
  1. 211  if (linenums == OPT_ONPLUS)
  2. 212         {
  3. 213                 char buf[INT_STRLEN_BOUND(pos) + 2];
  4. 214                 int n;
  5. 215
  6. 216                 linenumtoa(linenum, buf);
  7. 217                 n = strlen(buf);
  8. 218                 if (n < MIN_LINENUM_WIDTH)
  9. 219                         n = MIN_LINENUM_WIDTH;
  10. 220                 sprintf(linebuf+curr, "%*s ",n, buf);
  11. 221                 n++;  /* One space after the line number. */
  12. 222                 for (i = 0; i < n; i++)
  13. 223                         attr[curr+i] = AT_NORMAL;
  14. 224                 curr += n;
  15. 225                 column += n;
  16. 226                 lmargin += n;
  17. 227         }
复制代码

通过一个"sprintf"来打印.我原本的打算就是让行号在最前面显示,而不要留大块空白然后再行号,搞的行号跟正文贴太紧.所以我改成了" sprintf(linebuf+curr, "%-*s ",n, buf);",让它进行左对齐.这样效果倒也不错. 只是又没了颜色.....
回复 支持 反对

使用道具 举报

发表于 2010-8-31 18:23:08 | 显示全部楼层
gawk -v l=`wc -l $1|cut -d" " -f1|sed -e 's/.//'|wc -c` '{ printf "\x1b[34;01m%-*s \x1b[39;49;00m%s\n",l,NR,$0}' $1 |less

or

gawk -v l=`wc -l $1|cut -d" " -f1|sed -e 's/.//'|wc -c` '{ printf "\x1b[34;01m%*s \x1b[39;49;00m%s\n",l,NR,$0}' $1 |less
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-9-1 09:02:52 | 显示全部楼层
楼上的语句很不错,开始我以为速度会慢,试验了之后发现速度也不慢.色彩和对齐都有了. 但是,有一个比较致命的缺陷. 它一开始用gawk处理了文件然后传递给了less,这样导致的结果就是less所处理的这个文件实际上是个管道中间文件,增量显示不起作用了.我经常要用less查看日志,日志文件本身在不断更新.原本用 F命令可以直接跟踪显示最新更新的部分,采取这种方式后就不行了.

还是让人纠结啊^
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-9-3 15:50:00 | 显示全部楼层
琢磨了几天,终于找到办法了.我直接在sprintf那里写入ANSI字符,把代码改成了这样
  1. 211         if (linenums == OPT_ONPLUS)
  2. 212         {
  3. 213                 char buf[INT_STRLEN_BOUND(pos) + 2];
  4. 214                 int n;
  5. 215
  6. 216                 linenumtoa(linenum, buf);
  7. 217                 n = strlen(buf);
  8. 218                 if (n < MIN_LINENUM_WIDTH)
  9. 219                         n = MIN_LINENUM_WIDTH;
  10. 220                 sprintf(linebuf+curr, "\033[33;1m%-*s ",n,buf);
  11. 221                 n++;  /* One space after the line number. */
  12. 222                 for (i = 0; i < n; i++)
  13. 223                         attr[curr+i] = AT_NORMAL;
  14. 224                 curr += n;
  15. 225                 sprintf(linebuf+curr,"%s","\033[0m");
  16. 226                 n=n+4;
  17. 227                 curr+=4;
  18. 228                 column += n;
  19. 229                 lmargin += n;
  20. 230         }
复制代码

不过过程中还是有很多没搞清楚的地方. 比如为什么把颜色改回来的那段直接接在第一个sprintf后面不可以,非得我移动指针然后重新写一个.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表