Shell入门笔记:Linux批量提取文件名/shel文件名提取日期/NCL批量读取文件(shell脚本结合)

在大型计算时,我们会使用linux系统,而linux系统下使用Shell脚本进行一些批处理任务会十分方便,在这里,我将以我个人遇到的问题为例,结合Shell语言的一些常用命令和知识点,完成对于Shell的基础入门。

问题描述

我有来自美国国家冰雪中心的(NSIDC)的一些冰雪海冰数据文件,以nc储存,文件命名格式为:RDEFT4_yyyymmdd.nc
同时,我有一个NCL脚本,这个脚本可以对该数据进行插值导出。导出文件命名为FILE_yyyy-mm-dd.nc。
我的脚本只能针对于一个文件,我想加一个循环实现ncl脚本对这些文件的批量处理,而NCL在批量读取文件上的速度并不理想,因此,在这里我想将Shell脚本结合,从Shell中循环获取我想要的文件名,再在ncl中读取文件。
在这里插入图片描述
文件命名。

思路

根据文件命名特点,在NCL中,我们构造读取文件的方式为:

ymdd1="20180510"
ymdd2="2018-05-10"
data_filename="RDEFT4_"+ymdd1+".nc"
f=addfile(data_filename,"r")
output_file_name = name+ymdd2+ ":" + DATE

从上可知,我们需要从文件名中得到对应的ymdd1,再将其转换为ymdd2格式,输入至NCL中。
因此我们的思路可以分为以下几步:
1、shell脚本获取对应文件名
2、shell从对应文件名提取日期date1
3、shell将date1格式转变为yyyy-mm-dd格式,存入date2。
4、将date1、date2作为变量输入至NCL。
5、在shell脚本中,循环执行NCL。
下面,我们将首先简单介绍这几步中使用到的shell命令和知识点,再结合实例撰写代码脚本,并根据知识点进行代码解析,

相关Shell命令介绍

循环与条件语句

Linux下的循环与条件语句并没有什么特别,与其他语言类似,循环主要分为:

1、for循环,又之为条件循环,或者for i in ,其循环次数和给与的条件是成正比的,基本使用结构为:

for 变量名 in 取值列表
do
命令序列
done

2、until循环,条件测试循环,只要条件不成立则反复循环。

until 条件测试操作
do  
   命令序列
done

3、While循环,与untill相反,只要满足输入条件,则开始循环

while语句结构
while 条件测试操作
do
   命令序列
done

条件则分为:
1、test命令,测试条件是否成立,成立返回1,不成立返回0,主要进行逻辑判断,常用于测试权限和文件目录是否存在。
2、If语句,主要进行条件测试,满足则执行命令,不满足则不执行,常与for循环连用。
3、case语句,用于多在情景下的输出:常用于分类输出,如,输出学生成绩分段等。
关于循环与条件语句,可参照这两篇博文理解:Linux条件测试 Linux循环架构
在本次实例中,主要是用For循环与if语句结合。

Linux变量

Linux的变量可分为:环境变量与自定义变量。
在lshell中,当你想定义一个变量时,非常简单,只需:变量名=赋值内容,即可完成变量定义与赋值。
值得注意的是,变量名称依然有着它的规范:如能使用英文字母,数字和下划线,首个字符不能以数字开头。中间不能有空格,可以使用下划线(_)、不能包含特殊字符等等。
特别地,变量赋值时,=两端不能有空格,否则赋值失败。
当我们想使用自己定义的变量时,需要用$varname来使用,否则shell无法判断这是命令还是变量。

Shell中的特殊字符

Shell 特殊字符纷繁复杂,在shell中,如果无法正确的使用各种特殊符号,则会对我们执行命令带来许多麻烦。可分为:特殊变量,替换符,转义字符,字符串符(引号),功能符,运算符。
这些字符数量众多却零碎,依靠死记硬背并不现实,因此建议使用者先有一个初步的概念,在真正使用时再去查询用法。
特殊字符的整理可见:Shell特殊字符在本文中,我们主要使用以下字符:
1、$符号来定义变量
2、‘’ " "单双引号表明字符串
3、``英文半角符号,作为声明整句作为命令执行。
4、{}花括号,分隔扩展。
5、正则与贪婪匹配文件名日期等等。

Shell正则匹配/通配符(贪婪与非贪婪匹配)

Shell中的正则与通配符属于Shell中的特殊字符,主要用于提取字符串中对应的信息。
贪婪匹配可以用于匹配输入的字符,一般油% #表示,%是从右向左匹配,#则是从左向右匹配。
%为非贪婪匹配,即匹配最短结果。%从右到左进行非贪婪匹配,如:

v=http.123.com
echo ${v%.*}

通过非贪婪匹配,会匹配到.com,随后便将匹配到的字符删去,随后返回:http.123,通过贪婪匹配可以提取对应的文件名。
正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。在Shell中,grep、awk、sed 等命令可以支持正则表达式。
grep 命令用来行提取字符串;cut 命令用来列提取字符串;sed则为一种轻量编辑器,主要通过与正则结合,对文本进行匹配编辑。
在本文中,我们使用grep命令来提取日期。

Shell中的列表(List)

Shell中也有着让我们储存变量的类型,当我们有着多个变量时,便可选择列表(List)进行存储。
shell中列表的定义也非常简单,只需listname=()便可定义一个空列表,随后,这个空列表便可以在循环中不断赋值。
通过类似于切片的操作,可以得到列表哦某一特定下标的元素:

echo ${listTest[1]} #输出列表第二个元素
echo ${listTest[@]} #输出所有List

在本次实例中,我们会定义空列表,来存放提取的文件名与对应日期。

ls命令

ls命令是linux下最常用的命令,是list的缩写,通常用来打印出路径下所有文件名,格式为:

ls [选项] [目录名]
-a 显示所有文件及目录 (. 开头的隐藏文件也会列出)
-l 除文件名称外,亦将文件型态、权限、拥有者、文件大小等资讯详细列出
-r 将文件以相反次序显示(原定依英文字母次序)
-t 将文件依建立时间之先后次序列出
-A 同 -a ,但不列出 "." (目前目录)".." (父目录)
-F 在列出的文件名称后加一符号;例如可执行档则加 "*", 目录则加 "/"
-R 若目录下有文件,则以下之文件亦皆依序列出

本次实例中,通过ls命令,将符合要求的文件列入循环中。

echo命令

echo命令是一个内置在Bash中的shell,通常用于shell脚本中以显示消息或输出其他命令的结果。

echo [选项] string

echo除了可以用来打印相应的变量,来判断脚本执行情况外,还可以作为参数传递给变量,不过需要注意,在将参数传递给echo命令之前,shell将替换所有变量、通配符匹配和特殊字符。同时,在使用时,应当注意单双引号的使用。

grep命令

Linux grep 命令用于查找文件里符合条件的字符串。

grep [-abcEFGhHilLnqrsvVwxy][-A<显示行数>][-B<显示列数>][-C<显示列数>][-d<进行动作>][-e<范本样式>][-f<范本文件>][--help][范本样式][文件或目录...]

我们可以通过grep命令结合正则,提取出文件名的日期。

Shell中的日期(date命令)

Linux date 命令可以用来显示或设定系统的日期与时间,其中Formate规定了日期输出的格式。

date [OPTION]... [+FORMAT]
-d, --date=STRING:通过字符串显示时间格式,字符串不能是'now'。
-f, --file=DATEFILE:类似于--date; 一次从DATEFILE处理一行。
-I[FMT], --iso-8601[=FMT]:按照 ISO 8601 格式输出时间,FMT 可以为'date'(默认)'hours''minutes''seconds''ns'。 可用于设置日期和时间的精度,例如:2006-08-14T02:34:56-0600。
-R, --rfc-2822 : 按照 RFC 5322 格式输出时间和日期,例如: Mon, 14 Aug 2006 02:34:56 -0600。
--rfc-3339=FMT:按照 RFC 3339 格式输出,FMT 可以为'date', 'seconds','ns'中的一个,可用于设置日期和时间的精度, 例如:2006-08-14 02:34:56-06:00。
-r, --reference=FILE:显示文件的上次修改时间。
-s, --set=STRING:根据字符串设置系统时间。
-u, --utc, --universal:显示或设置协调世界时(UTC)。
--help:显示帮助信息。
--version:输出版本信息。

格式化输出:

date +"%Y-%m-%d"
2019-12-07
#输出当前时间2s后时间
date -d "2 second" +"%Y-%m-%d %H:%M.%S"
2018-11-20 14:21.31

在本例中,我们使用date参数,进行date格式的转换,即将yyyymmdd格式转为yyyy-mm-dd

操作-实例

文件遍历

首先,应该将文件夹所有符合要求的文件遍历,输入循环中。
这里我们要提取所有以RDEFT4开头的文件,使用ls命令与for循环。

#!/bin/bash
for file in $(ls [RDEFT4_]*)#遍历所有RDEFT4_开头文件,作为循环输入

提取文件名

这里使用到了贪婪匹配,与变量定义

file_list=() #定义存放文件名的空列表
do
filename=${file%.*} #get the name
        #echo ${filename}
        file_list[${#file_list[*]}]=${filename} #save name

提取日期/格式转换

使用grep从文件名中查找,并用date转换格式

date1=()
date2=()
         basedate1=`echo ${filename} |grep -Eo '[[:digit:]]{8}'` #get date
        basedate2=`date +%Y-%m-%d -d "${basedate1}"` #change format
        date1[${#date1[*]}]=${basedate1}
        date2[${#date2[*]}]=${basedate2}
        #echo ${basedate2}

与NCL结合

以上的代码我们提出了日期,并以两种格式存储,我们需要将这两种格式,循环输出到ncl中。
在ncl里有getenv()函数,可以从shell脚本中获取环境变量,因此我们可以实现:

ymdd1=getenv("basedate1")
ymdd2=getenv("basedate2")#从shell中读取环境变量
 export basedate1=`echo ${filename} |grep -Eo '[[:digit:]]{8}'` #get date
 export basedate2=`date +%Y-%m-%d -d "${basedate1}"` #change format
 ncl wrint_int_RDEFT4.ncl

done

以上便完成了全部操作。

完整代码&小结

Shell脚本的使用让我们在Linux系统下的操作效率大幅度提升,而shell语言本身比之普通的计算语言如:matlab、R、python并无太大区别,只要注意语法细节便可。
语言的入门往往需要以实践为基础,从个人来看,遍历文件夹获取文件名并其中提取日期/数字的操作很适合作为一个入门练习,因为它涉及到了不少基础知识点(循环、变量、匹配、输出、格式转换),同时也非常实用(尤其是对文件名有日期格式要求,而日期不连续的情况下)
shell脚本实现的资源相对较少,希望这篇博文能给后来者起到一定帮助。
完整代码:

#!/bin/bash
file_list=()
date1=()
date2=()
for file in $(ls [RDEFT4_]*)
do 
        filename=${file%.*} #get the name
        #echo ${filename}
        file_list[${#file_list[*]}]=${filename} #save name
        export basedate1=`echo ${filename} |grep -Eo '[[:digit:]]{8}'` #get date
        export basedate2=`date +%Y-%m-%d -d "${basedate1}"` #change format
        #date1[${#date1[*]}]=${basedate1}
        #date2[${#date2[*]}]=${basedate2}
        #echo ${basedate2}
        ncl wrint_int_RDEFT4.ncl

done
#echo ${file_list[*]}
#echo ${date1[*]}
#echo ${date2[*]}
  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
shell脚本中循环执行ncl脚本的示例代码如下: ``` #!/bin/bash path=/path/to/your/ncl/files # 设置ncl文件所在的路径 files=$(ls /path/to/your/data/files/*.nc) # 获取所有要处理的数据文件 for file in ${files[@}; do filename=$(basename $file) # 获取文件名 basedate=$(echo ${filename} | grep -Eo '[[:digit:]]{8}') # 从文件名提取日期 basedate_formatted=$(date -d "${basedate}" +%Y-%m-%d) # 将日期转换为指定格式 export basedate1=${basedate} # 将日期作为环境变量传入ncl脚本 export basedate2=${basedate_formatted} ncl ${path}/your_ncl_script.ncl # 执行ncl脚本 done ``` 在上述示例代码中,你需要将`/path/to/your/ncl/files`替换为你的ncl脚本所在的路径,将`/path/to/your/data/files/*.nc`替换为你的数据文件所在的路径和文件名模式。然后,将`your_ncl_script.ncl`替换为你的ncl脚本文件名。 这段shell脚本会循环遍历指定路径下的所有nc数据文件,提取文件名中的日期,并将日期作为环境变量传入ncl脚本中。然后,执行ncl脚本进行处理。通过这种方式,你可以实现批量处理nc数据文件的目的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Shell入门笔记Linux批量提取文件名/shel文件名提取日期/NCL批量读取文件(shell脚本结合)](https://blog.csdn.net/weixin_43750300/article/details/127560093)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [shell文件循环向NCL脚本传入参数 并执行NCL脚本](https://blog.csdn.net/weixin_44541877/article/details/131605581)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值