找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
楼主: DAIC

[问题求助] Perl怎样把一个文件中的内容行列互置?

[复制链接]
发表于 2011-6-11 16:45:24 | 显示全部楼层
本帖最后由 523066680 于 2011-6-11 17:12 编辑
11# 523066680


我是初学者,别跟我一般见识呀。
不过你的方法不能处理这种情况:
1 1 1
22 22 22
DAIC 发表于 2011-6-11 16:40

那就是按空格作为"字符串"分隔啦   俺学习下sxw的答案

  1. $n=0;
  2. $big=0;
  3. foreach (<DATA>) {
  4.         @{$arr[$n]}=split(" ",$_);
  5.         $big = $#{$arr[$n]} > $big ? $#{$arr[$n]} : $big;
  6.         $n++;
  7. }
  8. foreach $j (0..$big) {
  9.         foreach $i (0..$#arr) {
  10.                 print "$arr[$i][$j] ";
  11.         }
  12.         print "\n";
  13. }
  14. <STDIN>;

  15. __DATA__
  16. 1 2 3 4
  17. a b c dd
复制代码
没有考虑参差不齐的情况
发表于 2011-6-12 10:02:16 | 显示全部楼层
如果处理的是中文呢?比如:

  1.      将进酒—李白
  2. 君不见,黄河之水天上来,奔流到海不复回。
  3. 君不见,高堂明镜悲白发,朝如青丝暮成雪。
  4. 人生得意须尽欢,莫使金樽空对月。
  5. 天生我材必有用,千金散尽还复来。
  6. 烹羊宰牛且为乐,会须一饮三百杯。
  7. 岑夫子,丹丘生,将进酒,杯莫停。
  8. 与君歌一曲,请君为我侧耳听:
  9. 钟鼓馔玉不足贵,但愿长醉不复醒。
  10. 古来圣贤皆寂寞,唯有饮者留其名。
  11. 陈王昔时宴平乐,斗酒十千恣欢谑。
  12. 主人何为言少钱,径须沽取对君酌。
  13. 五花马,千金裘,呼儿将出换美酒,
  14. 与尔同销万古愁。
复制代码
发表于 2011-6-12 14:59:59 | 显示全部楼层
本帖最后由 523066680 于 2011-6-12 15:19 编辑

不在乎代码长度了,做了看看先
环境:perl, v5.10.1 built for MSWin32-x86-multi-thread
该脚本保存后,另存,选UTF-8文本格式 否则输出乱码
(我对编码处理还是很菜的)

  1. use Encode;
  2. open WRITE,">result.x";
  3. $L=0;
  4. $big=0;
  5. foreach (<DATA>) {
  6.         chomp;
  7.         Encode::_utf8_on($_);
  8.         $big=(length($_)-1)>$big? (length($_)-1):$big;
  9.         for $i (0..(length($_)-1)) {
  10.                 $arr[$L][$i]=substr($_,$i,1);
  11.         }
  12.         $L++;
  13. }
  14. foreach $j (0..$big) {
  15.         foreach $i (0..($L-1)) {
  16.                 if (! defined $arr[$i][$j]) {
  17.                         print WRITE " ";
  18.                 } else {
  19.                         print WRITE "$arr[$i][$j]";
  20.                 }
  21.         }
  22.         print WRITE "\n";
  23. }
  24. print "Press ENTER to quit\n";
  25. <STDIN>;
  26. __DATA__
  27.      将进酒—李白
  28. 君不见,黄河之水天上来,奔流到海不复回。
  29. 君不见,高堂明镜悲白发,朝如青丝暮成雪。
  30. 人生得意须尽欢,莫使金樽空对月。
  31. 天生我材必有用,千金散尽还复来。
  32. 烹羊宰牛且为乐,会须一饮三百杯。
  33. 岑夫子,丹丘生,将进酒,杯莫停。
  34. 与君歌一曲,请君为我侧耳听:
  35. 钟鼓馔玉不足贵,但愿长醉不复醒。
  36. 古来圣贤皆寂寞,唯有饮者留其名。
  37. 陈王昔时宴平乐,斗酒十千恣欢谑。
  38. 主人何为言少钱,径须沽取对君酌。
  39. 五花马,千金裘,呼儿将出换美酒,
  40. 与尔同销万古愁。
复制代码
 君君人天烹岑与钟古陈主五与
 不不生生羊夫君鼓来王人花尔
 见见得我宰子歌馔圣昔何马同
 ,,意材牛,一玉贤时为,销
 黄高须必且丹曲不皆宴言千万
将河堂尽有为丘,足寂平少金古
进之明欢用乐生请贵寞乐钱裘愁
酒水镜,,,,君,,,,,。
—天悲莫千会将为但唯斗径呼 
李上白使金须进我愿有酒须儿 
白来发金散一酒侧长饮十沽将 
 ,,樽尽饮,耳醉者千取出 
 奔朝空还三杯听不留恣对换 
 流如对复百莫:复其欢君美 
 到青月来杯停 醒名谑酌酒 
 海丝。。。。 。。。。, 
 不暮           
 复成           
 回雪           
 。。           
发表于 2011-6-12 15:15:56 | 显示全部楼层
引用资料:
源代码里的字符串的utf8 flag同样是关闭的状态.
假如你的源代码里含有中文, 那么你最好遵循这个原则: 1) 编写代码时使用utf8编码, 2)在文件的开头加上use utf8;语句. 这样, 你源代码里的字符串就都会是utf8编码的, 并且utf8 flag也已经打开.
3) 从文件读入. 这个毫无疑问, 你的文件是什么编码, 读进来就是什么编码了. 读进来以后, utf8 flag是off状态.

上楼的代码中 use Encode; 和 Encode::_utf8_on($_); 去掉
在开头 使用use utf8;  也可以。
 楼主| 发表于 2011-6-12 15:25:18 | 显示全部楼层
18# 523066680


这个有意思,怎样才能向古书那样从上向下、从右向左呢?
发表于 2011-6-12 15:51:38 | 显示全部楼层
本帖最后由 523066680 于 2011-6-12 16:14 编辑

反正是把文字一个个的存入行列式了,进了数组,爱怎么调换就怎么调换。
我这里倒是遇到一个奇怪的问题:
假如前面的代码不是读自身的__DATA__而是读取外部的一个utf-8编码的文本,
open READ,"<source.txt";
输出结果却是(注意将进酒标题 被往下推了一行):

君君人天烹岑与钟古陈主五与
 不不生生羊夫君鼓来王人花尔
 见见得我宰子歌馔圣昔何马同
 ,,意材牛,一玉贤时为,销
 黄高须必且丹曲不皆宴言千万
 河堂尽有为丘,足寂平少金古
将之明欢用乐生请贵寞乐钱裘愁
进水镜,,,,君,,,,,。
酒天悲莫千会将为但唯斗径呼 
—上白使金须进我愿有酒须儿 
李来发金散一酒侧长饮十沽将 
白,,樽尽饮,耳醉者千取出 
 奔朝空还三杯听不留恣对换 
 流如对复百莫:复其欢君美 
 到青月来杯停 醒名谑酌酒 
 海丝。。。。 。。。。, 
 不暮           
 复成           
 回雪           
 。。           

第一个字符编码好像改变了,看不见,但是判断又非空。 纳闷
=================================
找到了相关文章:
Ant编译utf-8非法字符:\65279 解决方法
http://blog.csdn.net/xiyuan1999/archive/2010/11/05/5989336.aspx
一般用UE或记事本编辑过的UTF-8的文件头会加入BOM标识,该标识由3个char组成。在 UTF-8的标准里该BOM标识是可有可无的

内牛满面的说,今天有收获,知道了这个有点坑人的东西。
发表于 2011-6-12 16:28:59 | 显示全部楼层
学习一下523066680版主的代码,哈哈

  1. use Encode;
  2. $n=0;
  3. $big=0;
  4. foreach (<DATA>) {
  5.          chomp;
  6.          $_=decode ("gb2312",$_);
  7.         @{$arr[$n]}=split(//,$_);
  8.         $big = $#{$arr[$n]} > $big ? $#{$arr[$n]} : $big;
  9.         $n++;
  10. }
  11. foreach $j (0..$big) {
  12.         foreach $i (reverse 0..$#arr) {
  13.                 printf("|%s", encode("gb2312",$arr[$i][$j])||'  ');
  14.         }
  15.         print "\n";
  16. }
  17. __DATA__
  18.           将进酒/李白
  19. 君不见,黄河之水天上来,奔流到海不复回。
  20. 君不见,高堂明镜悲白发,朝如青丝暮成雪。
  21. 人生得意须尽欢,莫使金樽空对月。
  22. 天生我材必有用,千金散尽还复来。
  23. 烹羊宰牛且为乐,会须一饮三百杯。
  24. 岑夫子,丹丘生,将进酒,杯莫停。
  25. 与君歌一曲,请君为我侧耳听:
  26. 钟鼓馔玉不足贵,但愿长醉不复醒。
  27. 古来圣贤皆寂寞,唯有饮者留其名。
  28. 陈王昔时宴平乐,斗酒十千恣欢谑。
  29. 主人何为言少钱,径须沽取对君酌。
  30. 五花马,千金裘,呼儿将出换美酒,
  31. 与尔同销万古愁。
复制代码

评分

参与人数 1PB +12 收起 理由
523066680 + 12 明显比我的好多了

查看全部评分

发表于 2011-6-12 16:35:45 | 显示全部楼层
本帖最后由 523066680 于 2011-6-12 16:39 编辑

明显比我的代码短很多啊
$arr[$i][$j])||'  '    仔细一看,用 || 真省事,没想到。
发表于 2011-6-12 16:38:39 | 显示全部楼层
20# DAIC


用reverse操作符啊
发表于 2026-3-29 21:53:01 | 显示全部楼层
本帖最后由 523066680 于 2026-3-29 22:03 编辑

间隔十几年,回来看,
其实 printf("|%s", encode("gbk", $arr[$i][$j])||' '); 这里应该把 || 放在 encode 里面,也就是
  1. printf("|%s", encode("gbk", $arr[$i][$j] || ' ') );
复制代码

有两个原因,
一、双空格在微软雅黑字体下,与1个汉字不等宽,改成 全角空格可以实现等宽 —— 全角空格也需 encode('gbk'
二、未定义的变量执行 encode ,在严格模式下可能触发异常,所以 `$变量 || '备用字符'` 甚至  defined $var ? $var : "备用字符" 比较安全。

|与|五|主|陈|古|钟|与|岑|烹|天|人|君|君| 
|尔|花|人|王|来|鼓|君|夫|羊|生|生|不|不| 
|同|马|何|昔|圣|馔|歌|子|宰|我|得|见|见| 
|销|,|为|时|贤|玉|一|,|牛|材|意|,|,| 
|万|千|言|宴|皆|不|曲|丹|且|必|须|高|黄| 
|古|金|少|平|寂|足|,|丘|为|有|尽|堂|河|将
|愁|裘|钱|乐|寞|贵|请|生|乐|用|欢|明|之|进
|。|,|,|,|,|,|君|,|,|,|,|镜|水|酒
| |呼|径|斗|唯|但|为|将|会|千|莫|悲|天|/
| |儿|须|酒|有|愿|我|进|须|金|使|白|上|李
| |将|沽|十|饮|长|侧|酒|一|散|金|发|来|白
| |出|取|千|者|醉|耳|,|饮|尽|樽|,|,| 
| |换|对|恣|留|不|听|杯|三|还|空|朝|奔| 
| |美|君|欢|其|复|:|莫|百|复|对|如|流| 
| |酒|酌|谑|名|醒| |停|杯|来|月|青|到| 
| |,|。|。|。|。| |。|。|。|。|丝|海| 
| | | | | | | | | | | |暮|不| 
| | | | | | | | | | | |成|复| 
| | | | | | | | | | | |雪|回| 
| | | | | | | | | | | |。|。| 
发表于 2026-3-29 22:01:17 | 显示全部楼层
自己那段,大致还是那个路径,只是加了些糖
  1. use utf8;
  2. use Encode;
  3. use List::Util qw/max/;
  4. STDOUT->autoflush(1);

  5. my $mat = [];
  6. # 逐行读取并写入数组
  7. while ( <DATA> )
  8. {
  9.     s/\r?\n//;
  10.     push @$mat, [split //];
  11. }

  12. # 获取最大列数(仅考虑全角空格)
  13. my $max_col = max( map { $#$_ } @$mat );

  14. for my $c ( 0 .. $max_col )
  15. {
  16.     print gbk(join("", map { $_->[$c] || " " } reverse @{$mat} )) ."\n";
  17. }

  18. sub gbk { encode('gbk', $_[0]) }

  19. __DATA__
  20.      将进酒—李白
  21. 君不见,黄河之水天上来,奔流到海不复回。
  22. 君不见,高堂明镜悲白发,朝如青丝暮成雪。
  23. 人生得意须尽欢,莫使金樽空对月。
  24. 天生我材必有用,千金散尽还复来。
  25. 烹羊宰牛且为乐,会须一饮三百杯。
  26. 岑夫子,丹丘生,将进酒,杯莫停。
  27. 与君歌一曲,请君为我侧耳听:
  28. 钟鼓馔玉不足贵,但愿长醉不复醒。
  29. 古来圣贤皆寂寞,唯有饮者留其名。
  30. 陈王昔时宴平乐,斗酒十千恣欢谑。
  31. 主人何为言少钱,径须沽取对君酌。
  32. 五花马,千金裘,呼儿将出换美酒,
  33. 与尔同销万古愁。
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-4-26 14:51

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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