Linux常用命令11Linux文本处理示例

0.AWK常变量含义

常变量名 含义
ARGC 命令行变元个数
ARGV 命令行变元数组
FILENAME 当前输入文件名
FNR 当前文件中的记录号
FS 输入域分隔符,默认为一个空格
RS 输入记录分隔符
NF 当前记录里域个数
NR 到目前为止记录数
OFS 输出域分隔符
ORS 输出记录分隔符

1、统计文本中单词数量,并进行排序

grep -Eo "[a-z|A-Z]+" words.txt|awk '{word_cound[$1]++}END {for(aword in word_cound){print aword,word_cound[aword]|"sort -rn -k2"}}'

2、电话号码验证
规则:
A、(xxx) xxx-xxxx
B、xxx-xxx-xxxx

grep -Eo '^(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}$' phonelist.txt

3、行列转换

awk '{for(i=0;++i<=NF;)t[i]=t[i]?t[i] FS $i:$i}END {for(i=0;i++<NF;)print t[i]}'  transport.txt

4、输出第10行

awk 'NR==10{print}' tenth.txt

这样的产品你会用吗?


这样的产品你会用吗?
作者:Hansen

首先,让我们来看一个小故事。

节选自:
龙枪编年史||,第三卷,第05章

人物介绍:
浓修:一个喜欢发明机械装置的侏儒
泰斯:一个喜欢游荡的坎德人
费资本:年迈老法师

前情提要:
泰斯和费资本要通过侏儒的投石机装置,从1楼飞到15楼

正文开始:

“三十五层楼高!”泰斯惊讶地重复。“住在顶楼不就倒霉了?这样得爬多少层阶梯啊?”

浓修吸吸鼻子。“我们早就舍弃了这种原始的装置。”他比着手势,“如果你不介意看看这些我们所制造出来的可怕科技成果吧——”

“我看到了。”泰斯把视线重新技回地面。“你们大概正准备打一场大规模的仗。我从来没看过这么多的投石器——”

坎德人硬生生吞回去接下来的话。正当他看着时,一声哨音响起,投石器把一个侏儒射出去。泰斯看见的并不是武器,而是一种取代楼梯的装置!

大厅的最底层放满了投石器,几乎含括了每一种侏儒制的投石器。有弹簧做的、十字弓形的、蒸汽机驱动的(还在实验阶段,他们在调整水的温度。)

投石器上下左右缠绕着数百里长的绳索,每一条绳索都连接着某种齿轮和机械装置,发出机器运转的声音。

  地板、墙壁、投石器上尽是各式各样的拉杆,成群结队的侏儒正努力地拉上拉下。

  “我想,”费资本听起来十分的无奈,“这个检验室应该不会在一楼吧?”

浓修摇摇头。“检验室在十五楼——”老法师发出一声心碎的叹息。

  坎德人听到一阵令人牙龈发酸的声音。

  “啊,他们准备好了。快来——”浓修说。

  泰斯快快乐乐、一跳一跳地跟在他后头,走向一个巨大的投石器。一名侏儒不耐烦地向他们打着手势,比了比后面一长串正排队等候着的侏儒。

泰斯跳上了投石器,满怀期待地看着天空。他可以看见许多侏儒从各楼层往下看,身旁环绕着各种机器、齿轮和说不出名字的装置,最容易分辨的是一种挂在墙壁上、类似棒子的东西。

浓修站在他旁边,皱着眉头。

  “敬老尊贤,年轻人,所以赶快离开让老人家坐上来。”他以他惊人的力量将泰斯从位置上拉下来,“魔法师优先——”

“喔,没关系啦!”费资本抗议,一个不小心,往后跌进一团绳子里。“我——我好像想起了一道可以让我飞到上头去的法术,浮空术,那是怎么施——施展?给我几分钟想一想……”

“一直叫我们快一点的是你那——”浓修生气地看着老法师,后头排队的侏儒开始鼓噪起来,彼此推挤。

  “啊!拼了啦!”老法师大吼,迈步爬过座位里,浓修在一边帮着。

负责发射投石器的株儒喊了一具不知道什么话。

  浓修指着上面,喊回去。“第十五层!”

技师走到五个拉杆之前,这里延伸出几近无限长的绳子。费资本哀怨地坐在投石器上,挣扎着要回想起他的法术。

  “预备!”浓修大喊,把泰斯拉近,好让他能看得更清楚,“用不了多久,技师就会给我们信号,对——就是这个信号——”

技师拉了拉一条绳子。

  “那有什么用?”泰斯插嘴。

  “这条绳子连接到第十五层的一个铃上,告诉他们有人要上来——”

“万一铃没响怎么办?”费资本大声地问。

  “会有第二个铃声提醒他们第一个铃没有响——”

“铃声没响底下会怎么应变?”

“就啥也不做。那是第十五层的事,不是你的问题——”

“万一他们不知道我要来了,这就变成我的问题了!”费资本大喊。“难不成要我就这样跳过去给他们一个惊喜吗?”

“啊!”浓修骄傲地说,“我跟你说——”

“我不玩了……”费资本表示。

  “不,等等。”浓修说,说话速度因为紧张而越来越快。“他们准备好了——”

“谁准备好了?”费资本愤怒地问。

  “第十五层!他们把网子放出来了,你知道——”

“网子!!!”费资本脸色发白,“够了!”他一只脚踏了出去。

  但在他逃出去之前,技师已经伸手拉下了第一根拉杆。一阵机械运转声后,投石器开始在轨道上移动。运转的震动又把费资本摔了回去,帽子遮住眼睛。

  “发生什么事了?”泰斯大喊。

  “他们正在就发射位置。”浓修大喊。“经度和纬度已经计算妥当,可以把乘客发射到预定的位置——”

“你给我说清楚网子是怎么一回事?”泰斯扯开喉咙大吼。

  “法师会飞上第十五层——喔!我向你保证,相当的安全——我们做过研究,事实上,研究结果证明了飞行比走路还要安全——等他飞到了轨迹的最高点,正要开始落下时,第十五层会伸出一张网,像这样抓住他”依修用一只手示范,啪的一声抓住一只蚊子,“然后把他丢——”

“这时间可得算得很准罗!”

“时间铁定准,因为我们研发出一种钩子来进行这项艰巨的任务,不过,”浓修嘟起嘴,皱眉说,“有些时候是投石器会出现误差,不过我们有个委员会——”

侏儒拉下拉杆,费资本尖叫着飞上天空。

  “喔哦!天哪!”浓修瞪着天空。“看来——”

“什么?什么?”泰斯大叫着想要看清楚。

  “网子又太早打开了——”浓修摇摇头,“第十五层今天一天已经发生了两次,这可得提案到安全网公会去讨论,并且不能让它再度发生——”

泰斯张大嘴,看着费资本的身影划过天空,借着投石器巨大的力量不断地往上飞。刹那间,坎德人终于懂了浓修在说些什么。

  第十五层的网子并没有在法师飞过第十五层之后张开而是在费资本飞越之前就张开了。费资本像是被打扁的苍蝇般贴在网子上。

  有短短的一瞬间,他手脚并用地小心抓着网子,然后……就掉了下来。

  钟声和锣声齐鸣。

  “别告诉我——”泰斯哀怨地说。“那就是网子失效的警告声。

  “你猜对了,但不用太紧张(自鸣得意地笑着)”浓修咯咯笑道,“因为这个警铃会触动第十三层的网子,正好可以——唉呦,看来好像迟了一步,不过没关系,我们还有第十二层——”

“快想想办法!”泰斯尖叫道。

“别穷紧张好不好!”浓修生气地说。“不然我根本没有机会说完我刚刚正要提到的最后后备安全系统,喔,来啦——”

泰斯惊讶地看着第三层墙壁上伸出了六个大筒子,底部打开来,掉出无数的海绵,铺在第一层的广场上。这是为了——显然的——预防所有的网子都没有接到。

很幸运的,第九层的网子没有失效,正巧来得及将法师捞起,之后网子随即收拢,把他甩到一个阳台上,侏儒们听见他不停的咒骂声,有点不大敢放他出来。

  “这下全部妥当!该你了。”浓修说。

  “最后一个问题!”泰斯坐在座位上对着浓修大喊。“万一这个后备安全系统也失效了怎么办?”

“好问题——”浓修高兴地说,“如果这些海绵掉下来不够快,那么另一个警铃会响起,将一大桶水倒到广场中央,然后呢——正好海绵这时候也该倒了下来——要擦干净地上的血迹就很简单了——”技师拉下了拉杆。

是不是很好笑?

问题是,我们是不是有一些产品,给到用户的时候:
1、一开始就做了很多错误的假设,用了错误的原型?
2、团队任务分工不明确,相互之间不Care?
3、不去预防问题发生,而是尝试各种Catch问题?
4、用了先进的技术,而忽略了用户的问题?
5、用户用差异的眼光看着你的时候,你仍自信的感觉那是称赞?

Spark环境搭建05

这里主要说一下Spark的SQL操作,如何从mysql导入数据。

#拷贝了mysql的驱动到jar文件下面
#建立DF
val jdbcDF = spark.read.format("jdbc").option("url", "jdbc:mysql://localhost:3307").option("dbtable", "hive.TBLS").option("user", "hive").option("password", "hive").load()

#schema
jdbcDF.schema

#count
jdbcDF.count()

#show
jdbcDF.show()

Spark环境搭建04

这里主要说一下Spark的SQL操作。

1、dataframe操作数据

#加载json数据
val df = spark.read.json("/usr/hadoop/person.json")
#加载CSV数据
#val df = spark.read.csv("/usr/hadoop/person.csv")

#查询前20行
df.show()

#查看结构
df.printSchema()

#选择一列
df.select("NAME").show()

#按条件过滤行
df.filter($"BALANCE_COST" < 10 && $"BALANCE_COST" > 1).show()

#分组统计
df.groupBy("SEX_CODE").count().show()

2、sql操作数据

#创建视图
df.createOrReplaceTempView("person")

#查看数据
spark.sql("SELECT * FROM person").show()

#统计数据
spark.sql("SELECT * FROM person").count()

#带条件选择
spark.sql("SELECT * FROM person WHERE BALANCE_COST<10 and BALANCE_COST>1 order by BALANCE_COST").show()

3、转为DS

#转为Dataset
case class PERSONC(PATIENT_NO : String,NAME : String,SEX_CODE : String,BIRTHDATE : String,BALANCE_CODE : String)
var personDS = spark.read.json("/usr/hadoop/person.json").as[PERSONC]

4、sql与map reduce混用

personDS.select("BALANCE_COST").map(row=>if(row(0)==null) 0.0 else (row(0)+"").toDouble).reduce((a,b)=>if(a>b) a else b)

spark.sql("select BALANCE_COST from person").map(row=>if(row(0)==null) 0.0 else (row(0)+"").toDouble).reduce((a,b)=>if(a>b) a else b)

5、数据映射为Class对象

val personRDD = spark.sparkContext.textFile("/usr/hadoop/person.txt")
val persons = personRDD.map(_.split(",")).map(attributes => Person(attributes(0), attributes(1), attributes(2), attributes(3), attributes(4).toDouble))

6、自定义schema

import org.apache.spark.sql.Row
import org.apache.spark.sql.types._

#加载数据
val personRDD = spark.sparkContext.textFile("/usr/hadoop/person.txt")
#转为org.apache.spark.sql.Row
val rowRDD = personRDD.map(_.split(",")).map(attributes => Row(attributes(0), attributes(1), attributes(2), attributes(3), attributes(4).replace("\"","").toDouble))
#定义新的Schema
val personSchema = StructType(List(StructField("PatientNum",StringType,nullable = true), StructField("Name",StringType,nullable = true), StructField("SexCode",StringType,nullable = true), StructField("BirthDate",StringType,nullable = true), StructField("BalanceCode",DoubleType,nullable = true)))
#建立新的DF
val personDF = spark.createDataFrame(rowRDD, personSchema)
#使用DF
personDF.select("PatientNum").show()

Spark环境搭建03

上面说到了Spark如何与Hadoop整合,下面就说一下Spark如何与HBase整合。

1、获取hbase的classpath

#要把netty和jetty的包去掉,否则会有jar包冲突
HBASE_PATH=`/home/hadoop/Deploy/hbase-1.1.2/bin/hbase classpath`

2、启动spark

bin/spark-shell --driver-class-path $HBASE_PATH

3、进行简单的操作

import org.apache.hadoop.hbase.HBaseConfiguration
import org.apache.hadoop.hbase.client.HBaseAdmin
import org.apache.hadoop.hbase.mapreduce.TableInputFormat
import org.apache.hadoop.hbase.io.ImmutableBytesWritable

val conf = HBaseConfiguration.create()
conf.set(TableInputFormat.INPUT_TABLE, "inpatient_hb")

val admin = new HBaseAdmin(conf)
admin.isTableAvailable("inpatient_hb")
res1: Boolean = true

val hBaseRDD = sc.newAPIHadoopRDD(conf, classOf[TableInputFormat], classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable], classOf[org.apache.hadoop.hbase.client.Result])

hBaseRDD.count()
2017-01-03 20:46:29,854 INFO  [main] scheduler.DAGScheduler (Logging.scala:logInfo(58)) - Job 0 finished: count at <console>:36, took 23.170739 s
res2: Long = 115077

Spark环境搭建02

1、启动spark

sbin/start-all.sh

可以在http://hiup:8080/看到spark运行情况。

2、启动shell

bin/spark-shell

3、测试

$ ./run-example SparkPi 10
Pi is roughly 3.140408

$ ./run-example SparkPi 100
Pi is roughly 3.1412528

$ ./run-example SparkPi 1000
Pi is roughly 3.14159016

4、基本操作

#HDFS加载数据
scala> var textFile=sc.textFile("/usr/hadoop/inpatient.txt")

#第一行
scala> textFile.first()
res1: String = "第一行内容"

#第一行,用逗号分割后,第一列(住院号)
textFile.first().split(",")(0)
res2: String = "0000718165"

#第一行,用逗号分割后,第5列(费用)
textFile.first().split(",")(5)
res3: String = "100.01"

#行数
scala> textFile.count()
res4: Long = 115411

#包含ICU的行数
textFile.filter(line=>line.contains("ICU")).count()
res5: Long = 912

#获取每一行的长度
var lineLengths = textFile.map(s=>s.length)

#获取总长度
var totalLenght = lineLengths.reduce((a,b)=>a+b)
totalLenght: Int = 32859905

#获取最大费用
textFile.map(line=>if(line.split(",").size==30) line.split(",")(23).replace("\"","") else "0").reduce((a,b)=>if(a.toDouble>b.toDouble) a else b)
res6: String = 300

#创建一个类
@SerialVersionUID(100L)
class PATIENT(var PATIENT_NO : String,var NAME : String,var SEX_CODE : String,var BIRTHDATE : String,var BALANCE_COST : String) extends Serializable 

#新建一个对象
var p=new PATIENT("PATIENT_NO","NAME","SEX_CODE","BIRTHDATE","BALANCE_COST")

#新建一个map函数
def mapFunc(line:String) : PATIENT = {
var cols=line.split(",")
return new PATIENT(cols(0),cols(1),cols(2),cols(3),cols(4))
}

#最大费用
textFile.filter(line=>line.split(",").size==30).map(mapFunc).reduce((a,b)=>if(a.BALANCE_COST.replace("\"","").toDouble>b.BALANCE_COST.replace("\"","").toDouble) a else b).BALANCE_COST

#男性最大费用
textFile.filter(line=>line.split(",").size==30).map(mapFunc).filter(p=>p.SEX_CODE=="\"M\"").reduce((a,b)=>if(a.BALANCE_COST.replace("\"","").toDouble>b.BALANCE_COST.replace("\"","").toDouble) a else b).BALANCE_COST

#女性最大费用
textFile.filter(line=>line.split(",").size==30).map(mapFunc).filter(p=>p.SEX_CODE=="\"F\"").reduce((a,b)=>if(a.BALANCE_COST.replace("\"","").toDouble>b.BALANCE_COST.replace("\"","").toDouble) a else b).BALANCE_COST

#退出
scala> exit

Spark环境搭建01

1、下载scala-2.11.1,并解压到/usr/scala/scala-2.11.1

2、下载spark-2.0.0-bin-hadoop2.4,并解压到/home/hadoop/Deploy/spark-2.0.0
(*如果要看后续文章,建议使用hadoop-2.5.2 hbase-1.1.2 hive-1.2.1 spark-2.0.0)

3、复制spark-env.sh.template为spark-env.sh,并添加下面几行

export JAVA_HOME=/usr/java/jdk1.7.0_79
export SCALA_HOME=/usr/scala/scala-2.11.1/
export SPARK_MASTER_IP=hiup01
export SPARK_WORKER_MEMORY=1g
export HADOOP_CONF_DIR=/home/hadoop/Deploy/hadoop-2.5.2/etc/hadoop

4、复制slaves.template为slaves,并添加下面几行

hiup01
hiup02
hiup03

5、将scala-2.11.1及spark-2.0.0复制到hiup02及hiup03

6、环境搭建完毕。

封神榜

Edsger Wybe Dijkstra 封神理由:
Algo60之父
算法大师
业界评价:
Rob Pike 封神理由:
Unix之父
UTF-8缔造者
业界评价:
Bill Joy 封神理由:
Unix之父
C语言之父
业界评价:
Ken Thompson 封神理由:
Unix之父
B之父
UTF-8编码发明者
ed作者
Go之父
业界评价:
Anders Hejlsberg 封神理由:
Turbo Pascal之父
Delphi之父
C#之父
业界评价:
Doug Cutting 封神理由:
Lucene作者
Nutch作者
Hadoop作者
业界评价:
Richard Stallman 封神理由:
GNU项目发起人,引起了业界革命
Emacs作者
GCC作者
GDB作者
GMake作者
业界评价:
Linus Torvalds 封神理由:
创造了Linux的开源开发模式,推动了整个编程世界的飞跃
Linux之父
业界评价:
“他简直优秀得无与伦比。”
Dennis M. Ritchie 封神理由:
BSD之父
vi作者
csh作者
Java规范作者之一
业界评价:
David Cutler 封神理由:
VMS首席设计师
Windows NT首席设计师
业界评价:
John Carmack 封神理由:
计算机图形领域大师
多款设计游戏的作者
业界评价:
Donald Knuth 封神理由:
The Art of Computer Programming作者
TeX作者
业界评价:
Jon Skeet 封神理由:
Stack Overflow总排名第一
业界评价:
如果他的代码没有通过编译的时候,编译器就会道歉。
Jeff Dean 封神理由:
Google搜索引擎幕后大神
业界评价:

Docker私有仓库搭建

1、安装registry

# sudo apt-get install docker docker-registry

2、上传镜像
2.1、客户端允许http

$ sudo vi /etc/defualt/docker
#添加这一行
DOCKER_OPTS="--insecure-registry 192.168.130.191:5000"

2.2、上传镜像

#查看镜像列表
$ sudo docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
elasticsearch                        5.1                 747929f3b12a        2 weeks ago         352.6 MB

#标记镜像
$ sudo docker tag elasticsearch:5.1 192.168.130.191:5000/elasticsearch

#查看镜像列表
$ sudo docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
elasticsearch                        5.1                 747929f3b12a        2 weeks ago         352.6 MB
192.168.130.191:5000/elasticsearch   5.1                 747929f3b12a        2 weeks ago         352.6 MB

#上传镜像
$ sudo docker push 192.168.130.191:5000/elasticsearch:5.1
The push refers to a repository [192.168.130.191:5000/elasticsearch]
cea33faf9668: Pushed
c3707daa9b07: Pushed
a56b404460eb: Pushed
5e48ecb24792: Pushed
f86173bb67f3: Pushed
c87433dfa8d7: Pushed
c9dbd14c23f0: Pushed
b5b4ba1cb64d: Pushed
15ba1125d6c0: Pushed
bd25fcff1b2c: Pushed
8d9c6e6ceb37: Pushed
bc3b6402e94c: Pushed
223c0d04a137: Pushed
fe4c16cbf7a4: Pushed
5.1: digest: sha256:14ec0b594c0bf1b007debc12e3a16a99aee74964724ac182bc851fec3fc5d2b0 size: 3248

3、查询镜像

$ curl -X GET http://192.168.130.191:5000/v2/_catalog
{"repositories":["alpine","elasticsearch","jetty","mongo","mysql","nginx","openjdk","redis","registry","ubuntu","zookeeper"]}

$ curl -X GET http://192.168.130.191:5000/v2/elasticsearch/tags/list
{"name":"elasticsearch","tags":["5.1"]}

#下面的查询命令总是报404错误,api文档中也没有,有些奇怪
$ curl -X GET http://192.168.130.191:5000/v2/search?q=elasticsearch
$ sudo docker search 192.168.130.191:5000/elasticsearch

4、下载镜像

$ sudo docker pull 192.168.130.191:5000/elasticsearch:5.1
5.1: Pulling from elasticsearch
386a066cd84a: Pull complete
75ea84187083: Pull complete
3e2e387eb26a: Pull complete
eef540699244: Pull complete
1624a2f8d114: Pull complete
7018f4ec6e0a: Pull complete
6ca3bc2ad3b3: Pull complete
424638b495a6: Pull complete
2ff72d0b7bea: Pull complete
d0d6a2049bf2: Pull complete
003b957bd67f: Pull complete
14d23bc515af: Pull complete
923836f4bd50: Pull complete
c0b5750bf0f7: Pull complete
Digest: sha256:14ec0b594c0bf1b007debc12e3a16a99aee74964724ac182bc851fec3fc5d2b0
Status: Downloaded newer image for 192.168.130.191:5000/elasticsearch:5.1

5、删除镜像

$ curl -X DELETE /v2/elasticsearch/manifests/5.1

参考github