[英]unix - cut command (adding own delimiter)
给定一个包含这样数据的文件(即 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\
更新(感谢 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
由于您在示例中使用了cut
。 假设每个字段都用制表符分隔:
$ cut --output-delimiter='|' -f1-3 input
id|store|No
2ttfgdhdfgh|1gfdkl-28|kgdl
9dhfdhfdfh|2t-33gdm|dgjkfndkgf
如果不是这种情况,请添加输入分隔符开关-d
我会使用 awk:
awk '{print $1 "|" $2 "|" $3}'
与其他一些建议一样,它假定列以空格分隔,并且不关心列号。 如果您在其中一个字段中有空格,它将不起作用。
基于字符位置而不是空格的更好的 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
如果你不害怕使用 perl,这里有一个单行:
$ perl -ne 'print join("|",unpack("A17A12A10", $_)), "\n";' input
unpack
调用将从输入行中提取一个 17 个字符的字符串,然后是一个 12 个字符的字符串,然后是一个 10 个字符的字符串,并将它们返回到一个数组中(去除空格)。 join
加入|
s。
如果您希望输入列采用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
。
只需您可以使用
cat stores.dat | tr -s ' ' '|'
据我所知,你不能用cut
做到这一点,但你可以用sed
轻松做到这一点,只要每列中的值永远不会有内部空格:
sed -e 's/ */|/g'
编辑:如果文件格式是真正的固定列格式,并且您不想使用 Mat 所示的perl
,则可以使用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
使用 'sed' 根据正则表达式搜索和替换文件的某些部分
用“|”替换空格来自 infile1
sed -e 's/[ \t\r]/|/g' infile1 > outfile3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.