700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Shell入门笔记:Linux批量提取文件名/shel文件名提取日期/NCL批量读取文件(shell脚本结合)

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

时间:2021-03-16 19:31:21

相关推荐

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

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

目录

问题描述思路相关Shell命令介绍循环与条件语句Linux变量Shell中的特殊字符Shell正则匹配/通配符(贪婪与非贪婪匹配)Shell中的列表(List)ls命令echo命令grep命令Shell中的日期(date命令)操作-实例文件遍历提取文件名提取日期/格式转换与NCL结合完整代码&小结

问题描述

我有来自美国国家冰雪中心的(NSIDC)的一些冰雪海冰数据文件,以nc储存,文件命名格式为:RDEFT4_yyyymmdd.nc

同时,我有一个NCL脚本,这个脚本可以对该数据进行插值导出。导出文件命名为FILE_yyyy-mm-dd.nc。

我的脚本只能针对于一个文件,我想加一个循环实现ncl脚本对这些文件的批量处理,而NCL在批量读取文件上的速度并不理想,因此,在这里我想将Shell脚本结合,从Shell中循环获取我想要的文件名,再在ncl中读取文件。

文件命名。

思路

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

ymdd1="0510"ymdd2="-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=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'。 可用于设置日期和时间的精度,例如:-08-14T02:34:56-0600。-R, --rfc-2822 : 按照 RFC 5322 格式输出时间和日期,例如: Mon, 14 Aug 02:34:56 -0600。--rfc-3339=FMT:按照 RFC 3339 格式输出,FMT 可以为'date', 'seconds','ns'中的一个,可用于设置日期和时间的精度, 例如:-08-14 02:34:56-06:00。-r, --reference=FILE:显示文件的上次修改时间。-s, --set=STRING:根据字符串设置系统时间。-u, --utc, --universal:显示或设置协调世界时(UTC)。--help:显示帮助信息。--version:输出版本信息。

格式化输出:

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

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

操作-实例

文件遍历

首先,应该将文件夹所有符合要求的文件遍历,输入循环中。

这里我们要提取所有以RDEFT4开头的文件,使用ls命令与for循环。

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

提取文件名

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

file_list=() #定义存放文件名的空列表dofilename=${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 datebasedate2=`date +%Y-%m-%d -d "${basedate1}"` #change formatdate1[${#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 dateexport basedate2=`date +%Y-%m-%d -d "${basedate1}"` #change formatncl wrint_int_RDEFT4.ncldone

以上便完成了全部操作。

完整代码&小结

Shell脚本的使用让我们在Linux系统下的操作效率大幅度提升,而shell语言本身比之普通的计算语言如:matlab、R、python并无太大区别,只要注意语法细节便可。

语言的入门往往需要以实践为基础,从个人来看,遍历文件夹获取文件名并其中提取日期/数字的操作很适合作为一个入门练习,因为它涉及到了不少基础知识点(循环、变量、匹配、输出、格式转换),同时也非常实用(尤其是对文件名有日期格式要求,而日期不连续的情况下)

shell脚本实现的资源相对较少,希望这篇博文能给后来者起到一定帮助。

完整代码:

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。