我正在尝试根据周数字段分隔大型管道分隔文件。该文件包含一整年的数据,因此有53周。我希望创建一个执行以下操作的循环:
1) check if week number is less than 10 - if it is paste a '0' in front
2) use grep to send the rows to a file (ie `grep '|01|' bigFile.txt > smallFile.txt` )
3) gzip the smaller file (ie `gzip smallFile.txt`)
4) repeat
是否有资源显示如何执行此操作?
编辑:
数据如下所示:
1|@gmail|1|0|0|0|1|01|com
1|@yahoo|0|1|0|0|0|27|com
我关心的专栏是右起第2位。
编辑2:
这是我正在使用的脚本,但它无法正常运行:
for (( i = 1; i <= 12; i++ )); do
#statements
echo 'i :'$i
q=$i
# echo $q
# $q==10
if [[ q -lt 10 ]]; then
#statements
k='0'$q
echo $k
grep '|$k|' 20150226_train.txt > 'weeks_files/week'$k
gzip weeks_files/week $k
fi
if [[ q -gt 9 ]]; then
#statements
echo $q
grep \'|$q|\' 20150226_train.txt > 'weeks_files/week'$q
gzip 'weeks_files/week'$q
fi
done
答案 0 :(得分:3)
在awk中很简单......
awk -F'|' '{ print > ("smallfile-" $(NF-1) ".txt";) }' bigfile.txt
编辑:为&#34; original-awk&#34;添加了括号。
答案 1 :(得分:2)
你快到了。
#!/bin/bash
for (( i = 1; i <= 12; i++ )); do
#statements
echo 'i :'$i
q=$i
# echo $q
# $q==10
#OLD if [[ q -lt 10 ]]; then
if [[ $q -lt 10 ]]; then
#statements
k='0'$q
echo $k
#OLD grep '|$k|' 20150226_train.txt > 'weeks_files/week'$k
grep "|$k|" 20150226_train.txt > 'weeks_files/week'$k
#OLD gzip weeks_files/week $k
gzip weeks_files/week$k
#OLD fi
#OLD if [[ q -gt 9 ]]; then
elif [[ $q -gt 9 ]] ; then
#statements
echo $q
#OLD grep \'|$q|\' 20150226_train.txt > 'weeks_files/week'$q
grep "|$q|" 20150226_train.txt > 'weeks_files/week'$q
gzip 'weeks_files/week'$q
fi
done
您并没有在变量值前面使用$
。你只能使用k或q在shell关节替换功能中没有$,即z=$(( x+k))
,或只是对(( k++ ))
之类的变量进行操作。还有其他人。
您需要了解单引号和dbl引用之间的区别。如果想要替换变量的值,则需要使用dbl-quoting,如行
grep "|$q|" 20150226_train.txt > 'weeks_files/week'$q
和其他人。
我猜你使用grep \'|$q|\' 20150226_train.txt
试图获得$q
的价值。
调试此类情况的方法是使用set -x
设置shell调试选项(使用set +x
将其关闭)。您将看到使用替换变量的值执行的每一行。高级调试需要echo "varof Interset now = $var"
(打印语句)。此外,您可以使用set -vx
(和set +vx
)在执行代码之前查看每行或阻止,然后-x
输出将显示实际执行的行。对于您的脚本,您会看到打印整个if ... elfi ...fi
块,然后只显示-x
输出的行以及变量值。即使经过多年的考虑,它也可能令人困惑。 ; - )
所以你可以通过前缀#OLD删除所有行,我希望你的代码能为你工作。
IHTH
答案 2 :(得分:2)
mkdir -p weeks_files &&
awk -F'|' '
{ file=sprintf("weeks_files/week%2d",$(NF-1)); print > file }
!seen[file]++ { print file }
' 20150226_train.txt |
xargs gzip
如果订购了您的数据,以便给定周数的所有行都是连续的,那么您可以使其更简单,更有效:
mkdir -p weeks_files &&
awk -F'|' '
$(NF-1) != prev { file=sprintf("weeks_files/week%2d",$(NF-1)); print file }
{ print > file; prev=$(NF-1) }
' 20150226_train.txt |
xargs gzip
答案 3 :(得分:1)
肯定有很多方法 - &#39; awk&#39;下面的行将重新格式化您的数据。如果你采用顺序方法,那么:
1)要重新格式化
awk -F '|' '{printf "%s|%s|%s|%s|%s|%s|%s|%02d|%s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9}' SOURCE_FILE > bigFile.txt
2)循环几个星期,创建一个zip文件小文件
for N in {01..53}
do
grep "|${N}|" bigFile.txt > smallFile.${N}.txt
gzip smallFile.${N}.txt
done
3)测试脚本显示重新格式化步骤
#!/bin/bash
function show_data {
# Data set w/9 'fields'
# 1| 2 |3|4|5|6|7| 8|9
cat << EOM
1|@gmail|1|0|0|0|1|01|com
1|@gmail|1|0|0|0|1|2|com
1|@gmail|1|0|0|0|1|5|com
1|@yahoo|0|1|0|0|0|27|com
EOM
}
###
function stars {
echo "## $@ ##"
}
###
stars "Raw data"
show_data
stars "Modified data"
# 1| 2| 3| 4| 5| 6| 7| 8|9 ##
show_data | awk -F '|' '{printf "%s|%s|%s|%s|%s|%s|%s|%02d|%s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9}'
示例运行:
$ bash test.sh
## Raw data ##
1|@gmail|1|0|0|0|1|01|com
1|@gmail|1|0|0|0|1|2|com
1|@gmail|1|0|0|0|1|5|com
1|@yahoo|0|1|0|0|0|27|com
## Modified data ##
1|@gmail|1|0|0|0|1|01|com
1|@gmail|1|0|0|0|1|02|com
1|@gmail|1|0|0|0|1|05|com
1|@yahoo|0|1|0|0|0|27|com