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

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

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

期望的输出:

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

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

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

每个剪辑之间插入一个分隔符的语法是什么?

奖金分(如果你可以提供这样的修剪值的选项):

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

更新(感谢马特的回答)我最终取得了成功的解决scheme – (这有点乱,但与我的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

如果你不害怕使用Perl,这里是一个单行的:

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

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

如果你想输入列是xy格式,而不写一个“真实”的脚本,你可以像这样破解(但它是丑陋的):

 #!/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

我会使用awk:

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

像其他一些建议一样,它假定列是空白分隔的,不关心列号。 如果在其中一个字段中有空格,则不起作用。

既然你在你的例子中使用了cut 。 假设每个字段用一个制表符分隔:

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

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

更好的基于字符位置的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 

使用'sed'根据正则表达式搜索和替换文件的部分

用'|'替换空格 来自infile1

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

就我所知,不能用cut来完成,但只要每列中的值不能有内部空格,就可以用sed轻松完成。

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

编辑:如果文件格式是一个真正的固定列格式,而你不想使用perl所示的Mat,这可以sed来完成,但它不是很漂亮,因为sed不支持数字重复量词.{17} ),所以你必须输入正确的点数:

 sed -e 's/^\(.................\)\(............\)\(..........\)$/\1|\2|\3/; s/ *|/|/g' 

如何使用只是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在注释中指出的那样,这个解决方案假定每一列由一个或多个空格分开,而不是由固定的长度分隔。