Windows 如何使用perl从.txt文件中选择特定列
我最近听说了Windows 如何使用perl从.txt文件中选择特定列,windows,perl,awk,Windows,Perl,Awk,我最近听说了awk和perl,我相信它们是处理原始数据文件的好工具,所以我想熟悉perl 我想和一个男孩一起玩。在这个文件中,首先有一些字符串。我要做的是在一个单独的.txt文件中打印一些列(即第1列和第4列),而不使用它们的单位 我知道我必须以某种方式使用连字符之间的行(-),所以这就是算法 问题是我不知道如何在perl中实现它。欢迎任何想法或帮助 该文件具有以下格式: =============================================================
awk
和perl
,我相信它们是处理原始数据文件的好工具,所以我想熟悉perl
我想和一个男孩一起玩。在这个文件中,首先有一些字符串。我要做的是在一个单独的.txt
文件中打印一些列(即第1列和第4列),而不使用它们的单位
我知道我必须以某种方式使用连字符之间的行(-
),所以这就是算法
问题是我不知道如何在perl中实现它。欢迎任何想法或帮助
该文件具有以下格式:
==================================================================
Calculation using SRIM-2006
SRIM version ---> SRIM-2008.04
Calc. date ---> December 05, 2013
==================================================================
Disk File Name = SRIM Outputs\Helium in Silicon
Ion = Helium [2] , Mass = 4.003 amu
Target Density = 2.3212E+00 g/cm3 = 4.9770E+22 atoms/cm3
======= Target Composition ========
Atom Atom Atomic Mass
Name Numb Percent Percent
---- ---- ------- -------
Si 14 100.00 100.00
====================================
Bragg Correction = 0.00%
Stopping Units = MeV / (mg/cm2)
See bottom of Table for other Stopping units
Ion dE/dx dE/dx Projected Longitudinal Lateral
Energy Elec. Nuclear Range Straggling Straggling
----------- ---------- ---------- ---------- ---------- ----------
500.00 keV 1.452E+00 3.238E-03 1.98 um 1891 A 2389 A
550.00 keV 1.449E+00 2.999E-03 2.13 um 1921 A 2443 A
600.00 keV 1.441E+00 2.795E-03 2.27 um 1951 A 2495 A
650.00 keV 1.430E+00 2.619E-03 2.42 um 1979 A 2545 A
700.00 keV 1.416E+00 2.466E-03 2.57 um 2007 A 2594 A
800.00 keV 1.384E+00 2.211E-03 2.88 um 2084 A 2689 A
900.00 keV 1.349E+00 2.007E-03 3.19 um 2160 A 2782 A
1.00 MeV 1.312E+00 1.839E-03 3.51 um 2237 A 2874 A
1.10 MeV 1.276E+00 1.700E-03 3.84 um 2314 A 2967 A
1.20 MeV 1.240E+00 1.581E-03 4.18 um 2392 A 3060 A
1.30 MeV 1.206E+00 1.479E-03 4.53 um 2471 A 3153 A
1.40 MeV 1.172E+00 1.390E-03 4.89 um 2551 A 3249 A
1.50 MeV 1.141E+00 1.312E-03 5.26 um 2633 A 3345 A
1.60 MeV 1.111E+00 1.243E-03 5.65 um 2716 A 3444 A
1.70 MeV 1.082E+00 1.181E-03 6.04 um 2801 A 3544 A
1.80 MeV 1.055E+00 1.126E-03 6.44 um 2888 A 3647 A
2.00 MeV 1.005E+00 1.030E-03 7.27 um 3176 A 3858 A
2.25 MeV 9.495E-01 9.320E-04 8.37 um 3605 A 4135 A
2.50 MeV 9.002E-01 8.522E-04 9.53 um 4031 A 4426 A
2.75 MeV 8.564E-01 7.857E-04 10.75 um 4456 A 4732 A
3.00 MeV 8.172E-01 7.294E-04 12.04 um 4883 A 5053 A
3.25 MeV 7.821E-01 6.811E-04 13.38 um 5312 A 5388 A
3.50 MeV 7.503E-01 6.391E-04 14.78 um 5744 A 5737 A
3.75 MeV 7.214E-01 6.024E-04 16.24 um 6180 A 6101 A
4.00 MeV 6.950E-01 5.698E-04 17.76 um 6619 A 6478 A
4.50 MeV 6.486E-01 5.148E-04 20.96 um 8162 A 7272 A
5.00 MeV 6.090E-01 4.700E-04 24.38 um 9630 A 8118 A
-----------------------------------------------------------
Multiply Stopping by for Stopping Units
------------------- ------------------
2.3211E+01 eV / Angstrom
2.3211E+02 keV / micron
2.3211E+02 MeV / mm
1.0000E+00 keV / (ug/cm2)
1.0000E+00 MeV / (mg/cm2)
1.0000E+03 keV / (mg/cm2)
4.6637E+01 eV / (1E15 atoms/cm2)
4.2914E+00 L.S.S. reduced units
==================================================================
(C) 1984,1989,1992,1998,2008 by J.P. Biersack and J.F. Ziegler
输出应包含来自六列的数据,但不包含其单位。此代码段应满足您的要求,并且您应该能够在不同长度的文件上使用它,只要所需的数字介于
-----------
之间:
my $infile = 'in.txt';
open my $input, '<', $infile or die "Can't open to $infile: $!";
my $count = 0;
while (<$input>){
chomp;
$count++ if /^-----/;
s/[a-zA-Z]//g;
print "$_\n" if $count == 1 and ! /^-----/;
next;
}
awk '$1~/-----------------------------------------------------------/ {f=0; exit}
$1~/-----------/ {f=1; next}
f{print $1, $3, $4, $5, $7, $9 > "output.txt"}' file
my$infle='in.txt';
用awk打开我的$input,:
$ awk 'NR>=25 && NR<=51 {print $1, $3, $4, $5, $7, $9 > "output.txt"}' file
$ cat output.txt
500.00 1.452E+00 3.238E-03 1.98 1891 2389
550.00 1.449E+00 2.999E-03 2.13 1921 2443
600.00 1.441E+00 2.795E-03 2.27 1951 2495
650.00 1.430E+00 2.619E-03 2.42 1979 2545
700.00 1.416E+00 2.466E-03 2.57 2007 2594
800.00 1.384E+00 2.211E-03 2.88 2084 2689
900.00 1.349E+00 2.007E-03 3.19 2160 2782
1.00 1.312E+00 1.839E-03 3.51 2237 2874
1.10 1.276E+00 1.700E-03 3.84 2314 2967
1.20 1.240E+00 1.581E-03 4.18 2392 3060
1.30 1.206E+00 1.479E-03 4.53 2471 3153
1.40 1.172E+00 1.390E-03 4.89 2551 3249
1.50 1.141E+00 1.312E-03 5.26 2633 3345
1.60 1.111E+00 1.243E-03 5.65 2716 3444
1.70 1.082E+00 1.181E-03 6.04 2801 3544
1.80 1.055E+00 1.126E-03 6.44 2888 3647
2.00 1.005E+00 1.030E-03 7.27 3176 3858
2.25 9.495E-01 9.320E-04 8.37 3605 4135
2.50 9.002E-01 8.522E-04 9.53 4031 4426
2.75 8.564E-01 7.857E-04 10.75 4456 4732
3.00 8.172E-01 7.294E-04 12.04 4883 5053
3.25 7.821E-01 6.811E-04 13.38 5312 5388
3.50 7.503E-01 6.391E-04 14.78 5744 5737
3.75 7.214E-01 6.024E-04 16.24 6180 6101
4.00 6.950E-01 5.698E-04 17.76 6619 6478
4.50 6.486E-01 5.148E-04 20.96 8162 7272
5.00 6.090E-01 4.700E-04 24.38 9630 8118
从windows命令行:
perl -F'-\s+-' -ane "print if (@F == 6 ... /--/) and !/--/ and s/ [a-z]+//gi" file
发件人:
如果您不想让它在下一次求值之前测试正确的操作数,就像在sed中一样,只需使用三个点(“…”)而不是两个点。在所有其他方面,“…”的行为就像“…”的行为一样
更新:
perl -lane "print qq{@F[0,2,3,4,6,8]} if (/^-/ ... /^-/) and !/^-/" file
使用严格;
使用警告;
打开my$f,“由于这是一个小文本文件,一个选项是将文件内容读入字符串,使用正则表达式捕获表,然后使用另一个正则表达式捕获列1和列4的VAL:
use strict;
use warnings;
my $content = do { local $/; <> };
my ($table) = $content =~ /-----\n(.+?)\n-----/s;
while ( $table =~ /(\S+)\s+([kM]eV).+?(\S+)\s+um/g ) {
print $2 eq 'keV' ? $1 * 1000 : $1;
print "\t$3\n";
}
命令行用法:>perlscript.pl infle[>outFile]
最后一个可选参数将输出定向到文件
第一行将文件内容写入$content
。第二行的正则表达式捕获-\n
和\n之间的所有文本(表),并将捕获的表放入$table
。最后,最后一个正则表达式全局“查找”列VAL(请注意,正则表达式使用列的单位来查找它们),并且在找到它们时,它们是打印的
希望这有帮助!请发布一些示例输入和所需的输出。@fedorqui:非常感谢您的评论!示例文件是,而输出将是紧挨着另一列的列,由制表符或空格分隔!输入文件不是同质的。另外,请注意,发布一些示例输入有助于提出问题,我将编辑我的答案立即提问!谢谢!这个文件确实不是本地的,这就是我认为perl可以处理它的原因。这里不是这样吗?@Thanos如果你刚刚开始,这纯粹是为了帮助你kern perl,我会从比这个更常规的东西开始。非常感谢你的回答!在这个文件中,你可以看到,例如真正的数据是从第25行到第51行。在第24行和第52行,你可以看到有一组连字符。所以“宝藏”"数据在这两组连字符之间。所以你要做的就是提取第24-53行之间的数据?我想提取并在一个seperate文件中打印从第25行到第51行的数据,在这些数字之间使用字符串;即单位。我注意到你正在使用行号。如果出现一个新文件,数据较长,但是ame格式,有没有一种方法可以使用连字符作为指针,指示数据的开始和结束。我正在尝试使用您的代码…语法如何?我正在使用perl data.pl
…如何告诉它哪个将成为输入?我试图用test.txt
替换代码中的input
,我还使用了e> perl data.pl test.txt
但它似乎没有任何作用……非常感谢你的回答!问题是,我不能在windows上使用awk
,那么,为什么你要用awk标记这个问题呢?还要注意,awk
可以在带有cygwin的windows中使用。带有cygwin
?哦,我不知道……我正在使用MinGW
不支持awk
…我将用Cygwin
替换MinGW
,希望它能工作!!!我还看到您正在使用行号。如果出现一个格式相同但数据数量不同的新文件,有没有其他方法可以这样做,而不必计算行数?@Thanos检查我更新的答案。这是从这个范围获取数据的另一种方法。非常感谢你的回答!!!问题是我只想打印数字。有没有办法去掉数字旁边的单位?这是不是用来计算标题字段的方法?我似乎得到了正确的答案用一个简单的触发器得到的结果是:perl-nlwe“print if/^-/…/^-/和!/^-/”
@TLP是的,这只是一种可能的方法;它更准确地跟随标题。@mpapec:我使用了perl-F'-\s+-'-ane“print if(@F==6…/-/)和!/-/和s/[a-z]+///gitest.txt>columns.txt
,效果很好!现在,我正在努力理解你的代码…如果我想打印没有单位的第1列和第4列,你的代码将如何更改?@Thanos检查更新;删除@F
的索引以过滤掉列非常感谢你的回答!我想我必须将你的代码保存在一个文件中(即data.perl),编译它(如何?)并执行它?将代码保存到file.pl
后,只需执行perl file.pl
。无需编译。还可以更改输入文件的名称(input
)如果需要的话。我的文件名为test.txt
。我将input
替换为,test
,test.txt
,但是我在data.pl第4行
没有这样的文件或目录。我想用test
或test.txt
替换.pl
和.txt
在同一个目录中。它应该是test.txt:打开我的$f,“我改变了
use strict;
use warnings;
my $content = do { local $/; <> };
my ($table) = $content =~ /-----\n(.+?)\n-----/s;
while ( $table =~ /(\S+)\s+([kM]eV).+?(\S+)\s+um/g ) {
print $2 eq 'keV' ? $1 * 1000 : $1;
print "\t$3\n";
}
500000 1.98
550000 2.13
600000 2.27
650000 2.42
700000 2.57
800000 2.88
900000 3.19
1.00 3.51
1.10 3.84
1.20 4.18
1.30 4.53
1.40 4.89
1.50 5.26
...