unix - cut命令(添加自己的分隔符)

时间:2011-12-25 14:35:22

标签: linux bash shell unix scripting

给定一个包含这样数据的文件(即stores.dat文件)

id               storeNo     type
2ttfgdhdfgh      1gfdkl-28   kgdl
9dhfdhfdfh       2t-33gdm    dgjkfndkgf

期望的输出:

id               |storeNo     |type
2ttfgdhdfgh      |1gfdkl-28   |kgdl
9dhfdhfdfh       |2t-33gdm    |dgjkfndkgf

想添加“|”这3个切割范围中的每一个之间的分隔符:

cut -c1-18,19-30,31-40 stores.dat

在每次剪切之间插入分隔符的语法是什么?

BONUS pts(如果您可以提供修剪值的选项):

id|storeNo|type
2ttfgdhdfgh|1gfdkl-28|kgdl
9dhfdhfdfh|2t-33gdm|dgjkfndkgf\

UPDATE(感谢Mat的回答)我最终在这个解决方案上取得了成功 - (它有点乱,但带有我的bash版本的SunOS似乎不支持更优雅的算术)

#!/bin/bash
unpack=""
filename="$1"
while [ $# -gt 0 ] ; do
    arg="$1"
    if [ "$arg" != "$filename" ]
    then
        firstcharpos=`echo $arg | awk -F"-" '{print $1}'`
        secondcharpos=`echo $arg | awk -F"-" '{print $2}'`
        compute=`(expr $firstcharpos - $secondcharpos)`
        compute=`(expr $compute \* -1 + 1)`
        unpack=$unpack"A"$compute
    fi
    shift
done
perl -ne 'print join("|",unpack("'$unpack'", $_)), "\n";' $filename 

用法:sh test.sh input_file 1-17 18-29 30-39

8 个答案:

答案 0 :(得分:5)

由于您在示例中使用了cut。 假设每个字段用制表符分隔:

$ cut  --output-delimiter='|' -f1-3 input
id|store|No
2ttfgdhdfgh|1gfdkl-28|kgdl
9dhfdhfdfh|2t-33gdm|dgjkfndkgf

如果不是这种情况,请添加输入分隔符开关-d

答案 1 :(得分:4)

我使用awk:

awk '{print $1 "|" $2 "|" $3}'

与其他一些建议一样,它假设列是空格分隔的,并不关心列号。如果其中一个字段中有空格,则无法正常工作。

答案 2 :(得分:2)

更好的基于角色位置的awk解决方案,而不是空白

$ awk -v FIELDWIDTHS='17 12 10' -v OFS='|' '{ $1=$1 ""; print }' stores.dat | tr -d ' '

id|storeNo|type
2ttfgdhdfgh|1gfdkl-28|kgdl
9dhfdhfdfh|2t-33gdm|dgjkfndkgf

答案 3 :(得分:1)

如果你不害怕使用perl,这里有一个单行:

$ perl -ne 'print join("|",unpack("A17A12A10", $_)), "\n";' input 

unpack调用将提取一个17字符串,然后是一个12字符串,然后从输入行中提取一个10字符串,并将它们返回到一个数组中(剥离空格)。 join添加| s。

如果您希望输入列为x-y格式,而不编写“真实”脚本,您可以像这样破解它(但它很难看):

#!/bin/bash
unpack=""

while [ $# -gt 1 ] ; do
    arg=$(($1))
    shift
    unpack=$unpack"A"$((-1*$arg+1))
done

perl -ne 'print join("|",unpack("'$unpack'", $_)), "\n";' $1 

用法:t.sh 1-17 18-29 30-39 input_file

答案 4 :(得分:0)

使用'sed'来搜索和替换基于正则表达式的文件部分

用'|'替换空格来自infile1

sed -e 's/[ \t\r]/|/g' infile1 > outfile3

答案 5 :(得分:0)

据我所知,您不能使用cut这样做,但只要每列中的值永远不会有 internal sed em>空格:

sed -e 's/  */|/g'

编辑:如果文件格式是真正的固定列格式,并且您不想使用Mat显示的perl,那么可以完成{{1但它不漂亮,因为sed不支持数字重复量词(sed),所以你必须键入正确的点数:

.{17}

答案 6 :(得分:0)

如何仅使用tr命令。

tr -s " " "|" < stores.dat

来自man页面:

-s      Squeeze multiple occurrences of the characters listed in the last
        operand (either string1 or string2) in the input into a single
        instance of the character.  This occurs after all deletion and
        translation is completed.

<强>测试

[jaypal:~/Temp] cat stores.dat 
id               storeNo     type
2ttfgdhdfgh      1gfdkl-28   kgdl
9dhfdhfdfh       2t-33gdm    dgjkfndkgf

[jaypal:~/Temp] tr -s " " "|" < stores.dat 
id|storeNo|type
2ttfgdhdfgh|1gfdkl-28|kgdl
9dhfdhfdfh|2t-33gdm|dgjkfndkgf

您可以轻松地将其重定向到这样的新文件 -

[jaypal:~/Temp] tr -s " " "|" < stores.dat > new.stores.dat

注意:正如Mat在评论中指出的那样,此解决方案假定每列由一个或多个空格分隔,并且不以固定长度分隔。

答案 7 :(得分:0)

您可以使用

cat stores.dat | tr -s ' ' '|'