【问题标题】:Assigning variables to values in a text file with 3 columns, line by line将变量分配给具有 3 列的文本文件中的值,逐行
【发布时间】:2013-07-26 23:26:20
【问题描述】:

我有一个 .txt 文件,它包含三列,每列由一个制表符分隔,264 行称为 PowerCoords.txt。每行包含一个 x(第 1 列)、y(第 2 列)和 z(第 3 列)坐标。我想逐行浏览这个文件,将每个值分配给 X、Y 和 Z,然后将这些变量输入到另一个函数中。

我是 bash 新手,我不明白如何指定我希望第 1 行、第 2 列中的值是变量 Y,依此类推......

我知道这可能非常简单,我可以在 Matlab 中快速完成,但我试图将所有内容都保存在 bash 中。

【问题讨论】:

  • 您所描述的不太可能是您想要做的任何事情的正确方法。如果您告诉我们更多关于您使用这 3 个值所做的事情,我们可以建议正确的方法。
  • 嗨 Ed - 这 3 个值是大脑中单个体素位置的 xyz 坐标。每行是一个体素的位置。这是我的输入文件。我有一个现有的函数,它需要 3 个输入(xyz)并围绕我输入的坐标创建一个 6 毫米的球体。我想从三列中的每一列中获取每个值,将其输入到我感兴趣的函数中,然后移动到下一行(行)并输入这三个值,依此类推......我希望这会有所帮助。感谢您的意见!
  • 例如第一行是:57 14 30(没有表头,每个值用制表符隔开)。我想将这些数字中的每一个标记为变量 X、Y 和 Z,然后使用 $X $Y $Z 将它们输入到另一个函数中。然后我想移动到下一行并做同样的事情,然后继续。
  • 当你说你有一个函数——一个shell函数还是别的什么?它们是否需要是单独的变量 X、Y. 和 Z,或者具有 3 个条目 a[1]、a[2]、a[3] 的数组 a 是否有效?
  • 数组也可以工作,只要我可以按照您的建议一次调用一个元素。

标签: bash variables awk text-files


【解决方案1】:
while read x y z; do
  echo x=$x y=$y z=$z
done < input.txt

以上要求您的所有列都不包含任何空格。

编辑:

针对 cme​​ts,这里有一种处理行编号的技术:

nl -ba < input.txt | while read line x y z rest; do
  ~/data/standard/MNI152_T1_2mm -mul 0 \
    -add 1 -roi $x 1 $y 1 $z 1 0 1 point -odt float > NewFile$line
done

【讨论】:

  • William - 我尝试了这个解决方案,但我无法让它发挥作用。 x y z 值在“while read x y z”循环中代表什么?我没有标记列,只有 3 列全是数字。
  • x、y 和 z 是您为列指定的名称。这将读取输入并将第一列分配给名为x 的变量,第二列分配给y,并将行的其余部分分配给z。当你尝试这个时会发生什么?
  • 同时读取 x y z; do > echo x=$x y=$y z=$z > done
  • 我应该补充一点,在此过程中,我还想跟踪每次分配 X、Y、Z 变量时我所在的行,以便我可以标记结果当我在第 23 行时,文件为 NewFile23。如果可能的话。
  • 听起来您的行中数据多于三列。一种典型的处理技术是while read x y z foo,这样额外的数据就不会分配给z。但听起来bash 确实是你正在做的错误的工具。
【解决方案2】:

William Pursell 的回答要聪明得多,但在我直截了当的初学者心中,我前段时间尝试过:

#!/bin/bash

data="data.dat"
datalength=`wc $data | awk '{print $1;}'`

for (( i=1; i<=$datalength; i++ )) ;do

x=`cat $data | awk '{print $1;}' | sed -n "$i"p | sed -e 's/[eE]+*/\\*10\\^/'` ; x=`echo "$x" | bc -l`       ; echo "x$i=$x";
y=`cat $data | awk '{print $2;}' | sed -n "$i"p | sed -e 's/[eE]+*/\\*10\\^/'` ; y=`echo "$y" | bc -l`       ; echo "y$i=$y";
z=`cat $data | awk '{print $3;}' | sed -n "$i"p | sed -e 's/[eE]+*/\\*10\\^/'` ; z=`echo "$z" | bc -l`       ; echo "z$i=$z";

# do something with xyz:

fslmaths ~/data/standard/MNI152_T1_2mm -mul 0 -add 1 -roi $x 1 $y 1 $z 1 0 1 point -odt float > NewFile$i

done

如果您喜欢使用浮点数并且输入也使用指数表示法,则必须添加 bcsed -e 's/[eE]+*/\\*10\\^/'

我遇到了类似的问题,但是对于大量输入数据,这些 bash 脚本非常慢。然后我迁移到perl。在 perl 中它看起来像这样:

#!/usr/bin/perl -w

use strict;

open (IN, "data.dat") or die "Error opening";

my $i=0;
for my $line (<IN>){
$i++;
open(OUT, ">NewFile$i.out");
chomp $line;
(my $x,my $y,my $z) = split '\t',$line;
print "$x $y $z\n";

# do something with xyz:

my $f= fslmaths ~/data/standard/MNI152_T1_2mm -mul 0 -add 1 -roi $x 1 $y 1 $z 1 0 1 point -odt float

print OUT "f= $f\n";
close OUT;
}
close IN;

【讨论】:

  • @Ed Morton 你能解释一下为什么我的解决方案有很多错误吗?我是来学习的,我对你的意见很感兴趣。
猜你喜欢
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
  • 2023-01-20
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
相关资源
最近更新 更多