3

我有一个数据文件和一个包含位置列表的文件,我想从数据文件的块中生成一个文件。例子:

$ cat data
abcdefghijkl
$ cat positions
0,2
5,8
$ cutter positions data
abcfghi

是否有一个(linux)shell 命令可以像我假设的“切割器”一样工作?“位置”的特定格式并不重要。我们可以假设“位置”中指定的块按递增顺序排列并且不重叠。可能还有一个额外的“切割器”模式,其中位置计数行而不是字节。

我可以自己轻松实现这样的程序,但我有直觉认为这样的程序已经存在。

4

3 回答 3

4

只需使用 bash 从参数扩展中提取子字符串,并使用positions给定的文件格式:

data=$(< data)    # read the entire file into a variable
while IFS=, read start stop; do
    printf "%s" "${data:$start:((stop-start+1))}"
done < positions
echo

输出

abcfghi

如果您的数据文件跨越多行,则必须注意位置文件以考虑换行符。

此方法不需要您将数据文件读入内存:

#!/bin/bash
exec 3<data
exec 4<positions
pos=0
while IFS=, read start stop <&4; do
    ((nskip = start - pos))
    ((nkeep = stop - start + 1))
    ((pos += nskip + nkeep))
    ((nskip > 0)) && read -N $nskip <&3
    read -N $nkeep <&3
    printf "%s" "$REPLY"
done
echo
于 2013-01-01T16:56:43.653 回答
3

cut -c将允许您指定固定宽度的列,这似乎是您正在寻找的:

$ echo "abcdefghijkl" | cut -c 1-3,6-9
abcfghi

请注意,字符位置从 1 而不是 0 开始。可以使用逗号指定各个列,例如cut -c 1,3,5,7,或者可以使用破折号指定范围:cut -c 2-8

于 2013-01-01T17:15:12.560 回答
2

这可以通过添加命令替换来完成,cut正如Barton Chittenden指出的那样:

$ cut -c $(cat positions) data
abcfghi

“位置”的特定格式并不重要。

我按照预期制作了职位格式,cut因此不需要额外的处理。

$ cat data
abcdefghijkl

$ cat positions
1-3,6-9

您可以通过在文件中cutter添加一个函数来将其转换为命令~/.bashrc

function cutter ()
{
     $ cut -c $(cat "$1") "$2"
}

然后运行source ~/.bashrc就可以cutter根据需要使用了:

$ cutter positions data
abcfghi

使用重定向将输出存储在newfile

$ cut -c $(cat positions) data > newfile

$ cutter positions data > newfile
于 2013-01-01T15:56:54.643 回答