【问题标题】:How do I select specific columns with the perl -lane command line?如何使用 perl -lane 命令行选择特定列?
【发布时间】:2019-01-10 07:35:06
【问题描述】:

下面的命令行适用于我

perl -F'\t' -lane'print join ",", @F[1,2]' inputfile

但我想传递一个可变的列列表,不一定是 @F[1,2] 中指定的第 1 列和第 2 列。

例如,根据输入文件的总列数,我想随机选择一个子集"$random-columns",并将其传递给@F[$random-columns]

我该怎么做?

我尝试首先生成一个 1 到 50 之间的 5 个随机列号的 columnList:

columnList=()
for (( i = 0; i <= 5-1; ++i ))
do
    (( randCol = ($RANDOM % 50) + 1 ))
    columnList[i]=$randCol
done

然后我做了以下插入逗号:

cols_new=$(IFS=,; echo "${columnList[*]}")

并尝试将其传递给 perl 命令行,如下所示(无效):

perl -F'\t' -lane'print join ",", @F[$cols_new]' inputfile

【问题讨论】:

标签: shell perl


【解决方案1】:

您的perl -e'...$cols_new...' 使用单壳引号,因此壳不插入变量。

虽然您可以使用插值或命令行参数从 shell 获取信息到 perl oneliner,但环境变量通常不那么麻烦:

export cols_new=1,2
perl -F'\t' -lane 'print join ",", @F[split /,/, $ENV{cols_new}]' inputfile

【讨论】:

  • 或者在一些简单的情况下(比如这个),只需将两个' 替换为",将"," 替换为'"'q(,)。如perl -F'\t' -lane "print join q(,), @F[split /,/, $cols_new]" inputfile。但我认为最好使用 perl 来生成随机数数组,就像@beasy 的答案一样。
  • @KjetilS。除了问题是“我想传递一个可变的列列表”。关于随机列的内容只是“例如”
【解决方案2】:

你可以在 Perl 中生成随机数:

perl -F'\t' -lane 'BEGIN { @cols = map int(rand 50) + 1, 1 .. 5 } print join ",", @F[@cols]' inputfile

【讨论】:

    【解决方案3】:

    使用rand

    从0到50的五个随机数:

    @randoms = map {int(rand(50))} 1..5;
    

    在你的单行中:

    perl -F'\t' -lane 'print join ",", @F[map {int(rand(50))} 1..5]' inputfile
    

    要对每一行使用相同的随机列索引,请使用在程序开始时只执行一次的BEGIN 块:

    perl -F'\t' -lane 'BEGIN {@rand = map {int(rand(50))} 1..5]}; print join ",", @F[@rand]' inputfile
    

    【讨论】:

    • 这将为每个输入行获得一组不同的随机列,这是一个非常不同的事情
    • int(rand(50)) 创建一个从 0 到 49,而不是 0 到 50 的随机整数。此外,这里不需要 int(),因为这些数字用于数组索引,Perl 会自动“整数”那些。
    • @ysth。如果我们需要每行相同的随机列,只需:perl -F'\t' -lane '@i=map rand(1+$#F), 1..5 if not @i; print join ",", @F[@i]' inputfile。这里使用 1+$#F 而不是 50,因为这允许文件恰好在其第一行具有任意数量的字段。
    • @KjetilS。 1+$#F 最好写成@F
    • @melpomene ← 同意,但我认为0+@F 更具可读性。 (并允许某些未来的 rand() 具有多个参数,尽管这不太可能)
    【解决方案4】:

    非常感谢大家!! 我按照您的建议解决了问题(见下文):

    • 从 2-$fileColumnCount 范围内随机选择 $extractColumnCount 列, 对它们进行排序并将它们放在 $cols_new_temp 中

    cols_new_temp=$(echo $(shuf -i 2-$fileColumnCount -n $extractColumnCount | sort -n))

    回声 $cols_new_temp

    • 这里我添加逗号来分隔列标签数组并将其放在 $cols_new 中

    cols_new=$(echo $cols_new_temp | sed 's/ /,/g')

    回声 $cols_new

    • 此 Perl oneliner 从 $file1 中指定的文件中检索预先指定的随机选择列 ($cols_new) 的子集,添加第一列和输出列。然后将生成的文件保存为 $file2

    output_col=1

    time perl -F',' -lane "print join q(,), @F[split "," $output_col,$cols_new]" $file1 > $file2

    【讨论】:

      猜你喜欢
      • 2015-05-02
      • 2012-11-27
      • 2018-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-11
      • 2018-08-24
      相关资源
      最近更新 更多