我有一个大型数据文件目录,我正在操作以获得所需格式的数据文件。它们每个都过早开始和结束15行,这意味着我需要从一个文件中删除前15行并将它们粘贴到序列中上一个文件的末尾。
首先,我编写了以下代码,将相关数据分成简单的块:
#!/bin/bash
destination='media/user/directory/'
for file1 in `ls $destination*.ascii`
do
echo $file1
file2="${file1}.end"
file3="${file1}.snip"
sed -e '16,$d' $file1 > $file2
sed -e '1,15d' $file1 > $file3
done
这很有效,所以下一步是世界上最简单的cat
命令:
cat $file3 $file2 > outfile
然而,我需要做的是将file2
拼接到之前的 file3
。目的Look at this screenshot以便更好地理解。
了解这些文件是如何随时间变化的:
*_20090412T235945_20090413T235944_* ### April 13
*_20090413T235945_20090414T235944_* ### April 14
所以我需要从上面的4月14日示例中删除15行并将其粘贴到4月13日示例的末尾。
这不一定是原始代码的一部分,事实上如果不是原始代码可能是最好的。我只是希望有人能够帮助我实现这一目标。
提前致谢!如果有任何我不清楚的事情,需要进一步解释,请告诉我。
答案 0 :(得分:4)
“我需要从一个文件中删除前15行并将它们粘贴到序列中前一个文件的末尾。”
如果我理解你想要什么,可以用一行代码完成:
awk 'NR==1 || FNR==16{close(f); f=FILENAME ".new"} {print>f}' file1 file2 file3
运行此操作后,文件file1.new
,file2.new
和file3.new
将以新形式传输,并传输一行。当然,您不限于三个文件:您可以在命令行中指定任意数量的文件。
为了简化我们的示例,让我们只删除前两行而不是15行。考虑这些测试文件:
$ cat file1
1
2
3
$ cat file2
4
5
6
7
8
$ cat file3
9
10
11
12
13
14
15
以下是运行我们命令的结果:
$ awk 'NR==1 || FNR==3{close(f); f=FILENAME ".new"} {print>f}' file1 file2 file3
$ cat file1.new
1
2
3
4
5
$ cat file2.new
6
7
8
9
10
$ cat file3.new
11
12
13
14
15
如您所见,每个文件的前两行已传输到前一个文件。
awk逐行隐式读取每个文件。我们的代码的工作是根据行号选择应该写入哪一行的新文件。变量f
将包含我们要写入的文件的名称。
NR==1 || FNR==16{f=FILENAME ".new"}
当我们正在阅读第一个文件的第一行NR==1
时,或者当我们正在阅读我们所处的文件的第16行FNR==16
时,我们将f
更新为是添加到.new
的当前文件的名称。
对于简短示例,我们使用了相同的代码,而FNR==16
替换为FNR==3
。
print>f
这会将当前行打印到文件f
。
(如果这是一个shell脚本,我们会使用>>
。这不是一个shell脚本。这是awk。)
destination='media/user/directory/'
awk 'NR==1 || FNR==16{close(f); f=FILENAME ".new"} {print>f}' "$destination"*.ascii
答案 1 :(得分:1)
您可以将之前的$file3
值存储在变量中(并检查它是否不是第一次使用-z
检查):
#!/bin/bash
destination='media/user/directory/'
prev=""
for file1 in $destination*.ascii
do
echo $file1
file2="${file1}.end"
file3="${file1}.snip"
sed -e '16,$d' $file1 > $file2
sed -e '1,15d' $file1 > $file3
if [ -z "$prev" ]; then
cat $prev $file2 > outfile
fi
prev=$file3
done
答案 2 :(得分:1)
你的任务并不困难。您希望收集目录中所有_end
个文件的列表(使用for
循环和globbing,而不是循环ls
的结果。获得所有end
文件后,您只需使用参数展开w / substing remove 解析日期为d1
和d2
以及日期1和日期2:
stuff_20090413T235945_20090414T235944_end
| d1 | | d2 |
然后,您只需将1
中的d1
减去date0或d0
,然后使用{{1}从d0
和d1
构建以前的文件名而不是_snip
。然后只测试前一个_end
文件名是否存在,如果存在,则将您当前的_snip
文件中的信息粘贴到上一个_end
文件中。 e.g。
_snip
测试输入文件
#!/bin/bash
for i in *end; do ## find all _end files
d1="${i#*stuff_}" ## isolate first date in filename
d1="${d1%%T*}"
d2="${i%T*}" ## isolate second date
d2="${d2##*_}"
d0=$((d1 - 1)) ## subtract 1 from first, get snip d1
prev="${i/$d1/$d0}" ## create previous 'snip' filename
prev="${prev/$d2/$d1}"
prev="${prev%end}snip"
if [ -f "$prev" ] ## test that prev snip file exists
then
printf "paste to : %s\n" "$prev"
printf " from : %s\n\n" "$i"
fi
done
示例使用/输出
$ ls -1
stuff_20090413T235945_20090414T235944_end
stuff_20090413T235945_20090414T235944_snip
stuff_20090414T235945_20090415T235944_end
stuff_20090414T235945_20090415T235944_snip
stuff_20090415T235945_20090416T235944_end
stuff_20090415T235945_20090416T235944_snip
stuff_20090416T235945_20090417T235944_end
stuff_20090416T235945_20090417T235944_snip
stuff_20090417T235945_20090418T235944_end
stuff_20090417T235945_20090418T235944_snip
stuff_20090418T235945_20090419T235944_end
stuff_20090418T235945_20090419T235944_snip
(当然用您的实际前缀替换$ bash endsnip.sh
paste to : stuff_20090413T235945_20090414T235944_snip
from : stuff_20090414T235945_20090415T235944_end
paste to : stuff_20090414T235945_20090415T235944_snip
from : stuff_20090415T235945_20090416T235944_end
paste to : stuff_20090415T235945_20090416T235944_snip
from : stuff_20090416T235945_20090417T235944_end
paste to : stuff_20090416T235945_20090417T235944_snip
from : stuff_20090417T235945_20090418T235944_end
paste to : stuff_20090417T235945_20090418T235944_snip
from : stuff_20090418T235945_20090419T235944_end
)
如果您有疑问,请告诉我。