我需要帮助编写一个脚本,该脚本可以从主文件中提取最旧的记录并将其保存在单独的文件中。该文件包含数百个 ISIN 代码和其他数据。每个都有每日记录。完美的脚本将取出整个最旧的行并将其保存在以该 ISIN 代码命名的单独文件中。所以我猜是 split 和 grep 组合?
例子:
A 列 - ISIN 代码(即 XX1234567891)<- 2 个字母和 10 个数字
C 列 - 日期 - 2019 年 8 月 4 日
B 列和 DI - 相关数据。
有什么建议吗?请记住,我才刚刚开始使用 bash。
预先感谢您的任何帮助
以下是示例文件的链接: https://drive.google.com/file/d/1Q3qhrVlIMA7cJhDVxjxoHCipEl8sV-xo/view?usp=sharing
具有 3 个不同 ISIN 的示例:
具有最旧记录的一个文件:
具有最旧记录的第二个文件:
第三个具有最古老记录的 - 两者的日期相同:
日期采用 DD/MM/YYYY 格式(现在我在 Libre 中查看它,我可以看到日期格式更改为 MM/DD/YYYY - 但我可以稍后调整)。
答案1
尝试这个,
tail -n+2 file \
| sort -n -k 3.7,3.10 -k 3.4,3.5 -k 3.1,3.2 \
| awk '!s[$1]++{print > $1}'
tail -n+2 file
只删除标题行sort -n -k 3.7,3.10 -k 3.4,3.5 -k 3.1,3.2
对日期进行排序。awk '!s[$1]++{print > $1}'
仅打印每个 ISIN 的第一行
如果您有YYYY/MM/DD
日期格式,那么您只需执行即可sort -k3
。
awk
唯一的解决方案:
awk '
NR==1{next}
{
split($3,d,"/")
t=mktime(d[3]" "d[2]" "d[1]" 00 00 00")
if(!s[$1]||t<s[$1]){
s[$1]=t
r[$1]=$0
}
}
END {
for (i in r) { print r[i] > i}
}' file
答案2
您在 GUI 界面中显示示例,在纯文本中列之间应该有分隔符,我使用空格作为分隔符,在脚本中用实际的分隔符替换它。
下面是我用作示例的文件:
$ cat ISIN
XX1234567890 Bcolumn 08/04/2019 Dcolumn
XX2234567890 Bcolumn 09/03/2019 Dcolumn
XX3234567890 Bcolumn 07/05/2019 Dcolumn
XX3234567890 Bcolumn 07/05/2018 Dcolumn
XX3234567890 Bcolumn 07/05/2016 Dcolumn
XX3234567890 Bcolumn 07/05/2017 Dcolumn
XX1234567890 Bcolumn 07/05/2015 Dcolumn
下面是一个脚本,它处理输入文件中最早的 3 行,您可以调整这个数字:
#!/usr/bin/env bash
# replace ISIN with actual file name
# head -n 3 results in 3 oldest rows
# note the field separator, replace it with actual
result=$(sort --field-separator=' ' --key=3.7,3.10 --key=3.4,3.5 --key=3.1,3.2 ISIN| head -n 3)
# if input contain header line following line will take that into account,
# uncomment it, and comment the above line
#result=$(tail -n+2 ISIN| sort --field-separator=' ' --key=3.7,3.10 --key=3.4,3.5 --key=3.1,3.2| head -n 3)
# read output line by line
# and delete exising files named as ISIN
# may be left from previous script run
while IFS='' read -r i || [[ -n "$i" ]]; do
# extracting first column
first=${i%% *}
rm $first &>/dev/null
done <<<$result
# read output line by line
while IFS='' read -r i || [[ -n "$i" ]]; do
echo "output: $i"
# extracting first column
first=${i%% *}
echo "Writing to file $first"
# append to a file with first column as a name
echo "$i" >>$first
done <<<$result
使用实际分隔符进行调整--field-separator=' '
,可能是“,”或“;”,并更改head -n 3
为所需的旧行数。脚本还会从 ISIN 文件读取输入,并将其替换为您的实际文件名。
更新:脚本将行附加到 ISIN 文件,因此在第二次运行时 - 可能会出现重复的行。我添加了一个循环,删除这个旧的 ISIN 文件并再次创建,因此可以多次运行并获得正确的结果。输出文件包含一个或多个具有相同 ISIN 的行。