mongodb的NUMA问题

mongodb日志显示如下:

WARNING: You are running on a NUMA machine.

We suggest launching mongod like this to avoid performance problems:

numactl –interleave=all mongod [other options]

解决方案:

1.在原启动命令前面加numactl –interleave=all

如# numactl –interleave=all ${MONGODB_HOME}/bin/mongod –config conf/mongodb.conf

2.修改内核参数

echo 0 > /proc/sys/vm/zone_reclaim_mode

http://www.mongodb.org/display/DOCS/NUMA

下面注释转自网络

一、NUMA和SMP

NUMA和SMP是两种CPU相关的硬件架构。在SMP架构里面,所有的CPU争用一个总线来访问所有内存,优点是资源共享,而缺点是总线争用激烈。随着PC服务器上的CPU数量变多(不仅仅是CPU核数),总线争用的弊端慢慢越来越明显,于是Intel在Nehalem CPU上推出了NUMA架构,而AMD也推出了基于相同架构的Opteron CPU。

NUMA最大的特点是引入了node和distance的概念。对于CPU和内存这两种最宝贵的硬件资源,NUMA用近乎严格的方式划分了所属的资源组(node),而每个资源组内的CPU和内存是几乎相等。资源组的数量取决于物理CPU的个数(现有的PC server大多数有两个物理CPU,每个CPU有4个核);distance这个概念是用来定义各个node之间调用资源的开销,为资源调度优化算法提供数据支持。

二、NUMA相关的策略

1、每个进程(或线程)都会从父进程继承NUMA策略,并分配有一个优先node。如果NUMA策略允许的话,进程可以调用其他node上的资源。

2、NUMA的CPU分配策略有cpunodebind、physcpubind。cpunodebind规定进程运行在某几个node之上,而physcpubind可以更加精细地规定运行在哪些核上。

3、NUMA的内存分配策略有localalloc、preferred、membind、interleave。localalloc规定进程从当前node上请求分配内存;而preferred比较宽松地指定了一个推荐的node来获取内存,如果被推荐的node上没有足够内存,进程可以尝试别的node。membind可以指定若干个node,进程只能从这些指定的node上请求分配内存。interleave规定进程从指定的若干个node上以RR算法交织地请求分配内存。

三、NUMA和swap的关系

可能大家已经发现了,NUMA的内存分配策略对于进程(或线程)之间来说,并不是公平的。在现有的Redhat Linux中,localalloc是默认的NUMA内存分配策略,这个配置选项导致资源独占程序很容易将某个node的内存用尽。而当某个node的内存耗尽时,Linux又刚好将这个node分配给了某个需要消耗大量内存的进程(或线程),swap就妥妥地产生了。尽管此时还有很多page cache可以释放,甚至还有很多的free内存。

四、解决swap问题

虽然NUMA的原理相对复杂,实际上解决swap却很简单:只要在启动MySQL之前使用numactl –interleave来修改NUMA策略即可。

值得注意的是,numactl这个命令不仅仅可以调整NUMA策略,也可以用来查看当前各个node的资源是用情况,是一个很值得研究的命令。

误删 libc.so.6的解决方法

今天不小心把libc.so.6给删除了。

原系统是这样的: libc.so.6 -> lib-2.6.1.so

本想新建立一个软链接,指向 lib-2.8.so

没想到 ln 命令不能用了。 原来linux 很多shell命令都离不开 libc.so.6。 真惨了。 幸好没有关linux.

从网上一查, 找到解决方案:

进入 /lib (或 /lib64 视情况而定),

#LD_PRELOAD=/lib/libc-x.x.x.so && ln -s /lib/libc-x.x.x.so libc.so.6

x.x.x表示系统libc的版本

就可以了

一定要记住自己系统使用的libc版本。

How-To: Install Google’s Android Eclipse Plugin (And/or Adb) on 64-bit Debian/Ubuntu

Today I had to reinstall the Android plugin on my system and I recently upgraded to a 64-bit development VM. To my surprise the installation didn’t go smoothly at all. After restarting Eclipse twice I was constantly presented with two error messages “Failed to parse the output of ‘adb version’” and “adb: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory”. Your system may also present another error message that reads “adb: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory”.

I could see that it was looking for libncurses.so.5 however I know that ncurses is already installed on my machine in /lib as /lib/libncurses.so.5. So where exactly was Eclipse/adb looking for it? It turns out that it wants to find its libraries in the /lib32 directory but you can’t just symlink it or you’ll get an error that reads “wrong ELF class: ELFCLASS64”. adb needs to have the 32-bit versions installed or it won’t function at all.

So to get up and running just run the following command to fix the issue:

sudo apt-get install lib32ncurses5 lib32stdc++6

After that just restart Eclipse and the issue should be fully put to bed. Let me know how it works out for you or if you run into trouble.

If you still run into trouble like an error message that reads “aapt: error while loading shared libraries: libz.so.1: cannot open shared object file: No such file or directory” you need to install the ia32-libs like this:

sudo apt-get install ia32-libs

Then rebuild your project and the errors should be gone.

UPDATE 2012-02-14: Rortian reports that the following command words on Fedora 16:

yum install ncurses-libs.i686 libstdc++.i686 libgcc.i686

use ssh to run shell script on a remote machine

Also, don’t forget to escape variables if you want to pick them up from the destination host.

This has caught me out in the past.

For example:

user@host> ssh user2@host2 “echo \$HOME”
prints out /home/user2

while

user@host> ssh user2@host2 “echo $HOME”
prints out /home/user

Another example:

user@host> ssh user2@host2 “echo hello world | awk ‘{print \$1}'”
prints out “hello” correctly.

Node.js V0.12新特性之给子进程的同步API

尽管发明Node.js的初衷主要是为了编写Web服务器,但开发人员又发现了其他适用(和不适用!)Node的用途。令人觉得惊喜的是,这些用途中有一个是编写shell脚本。并且那确实有意义:Node的跨平台支持已经相当好了,既然前端和后端都用JavaScript写了,如果构建系统也用JavaScript写不是更好吗,对吧?

异步对shell脚本的坏处

在这一用途上值得称道的库是Grunt,它是构建在ShellJS之上的。然而ShellJS有一块硬骨头要啃:Node迫使它用异步I/O。尽管对于Web服务器来说异步I/O很棒,因为它必须随时做出响应,但对于需要逐步执行的shell脚本来说,异步I/O意义不大。

所以,ShellJS的作者们发现了一个“有趣的”解决办法,让它可以运行一个shell命令,然后等着命令完成。大致上是下面这样的代码:

var child_process = require(‘child_process’);
var fs = require(‘fs’);

function execSync(command) {
// 在子shell中运行命令
child_process.exec(command + ‘ 2>&1 1>output && echo done! > done’);

// 阻塞事件循环,知道命令执行完
while (!fs.existsSync(‘done’)) {
// 什么都不做
}

// 读取输出
var output = fs.readFileSync(‘output’);

// 删除临时文件。
fs.unlinkSync(‘output’);
fs.unlinkSync(‘done’);

return output;
}
换句话说,在shell执行你的命令时,ShellJS依然在运行,并持续不断地轮询着文件系统,检查是否能找到表明命令已经完成的那个文件。有点儿像驴子。

这种效率低下又丑陋不堪的解决办法让Node核心团队受刺激了,实现了一个真正的解决方案 – Node v0.12最终应该会支持同步运行子进程。实际上这个特性已经在路线图上放了很长时间了– 我记得是在2011年的JSConf.eu上(!) ,跟现在已经退休的Node维护者Felix Geisendoerfer坐在一起,勾勒出了一个实现execSync的办法。在过了两年多以后,这一特性现在终于出现在了master分支上。

恭喜,ShellJS的人们挑了一个很好的刺儿! 🙂

同步对shell脚本的好处

我们刚加上的API spawnSync跟它的异步小伙伴类似,它提供的底层API让你可以完全掌控子进程的设置。它还会返回所有我们能够收集的信息:退出码、终止信号、可能的启动错误,以及这个进程的全部输出。当然,在流中使用spawnSync没有任何意义-它是同步的,所以事件处理器不能在进程退出前运行-所以进程的所有输出会被缓冲到一个单例字符串或缓冲对象中。

并且就像众所周知的exec(运行shell命令)和execFile(用于运行一个可执行文件)方法一样,我们为常见的情况添加了execSync和execFileSync,它们比spawnSync更易用。如果你用了这些API,Node会假定你关心的只是进程写到stdout中的数据。如果进程或shell返回了非零的退出码,node会认为出现错误了,exec(Sync)会抛出。

比如获取项目git历史的代码就像下面这样简单:

var history = child_process.execSync(‘git log’, { encoding: ‘utf8’ });
process.stdout.write(history);
现在你可能在想“怎么要用这么长时间?”从表面上看,启动一个子进程并读取它的输出看起来简直是小菜一碟。也确实是这样-如果你只关心非常常见的情况。但是,我们不想做出来的解决方案只是一半。

当需要同时发送输入并读取一或多个输出流时,有两个选择:用线程-或者用事件循环。比如Python的实现,我们发现他们或者用事件循环(在Unix系的平台上)或者用线程(在Windows上)。并且它的实现可真不是一碟小菜。

2011年我们就意识到Node已经有一个非常棒的事件循环库了,即libuv。理论上已经具备了实现这一特性的所有条件。然而总是有或大或小的问题,让它并不能真正可靠地工作。

比如说,当子进程退出时,kernel会给node发送一个SIGCHLD信号通知它,但当有多个事件循环存在时,有很长一段时间libuv都不能正确处理信号。还有,删除事件循环并且不留下堆栈跟踪的能力也是最近才加上的。之前Node根本不管,它只是在某点退出,然后让OS打扫战场。如果我们需要一个临时的事件循环,并且在不需要它后仍然继续运行,这种策略就不太合适了。

慢慢的,随着时间的推移,所有这些问题都被解决了。所以如果你现在再设法看看过去那些缓冲区管理、参数解析、超时处理等诸如此类的东西,你会发现这个特性的核心只是一个事件循环,带子进程、计时器,还有一堆附着在它上面的管道。

如果你不关心它都是如何运作的,只需要看看文档,让node为控制子进程提供的丰富选项震你一下吧。现在谁愿意去把ShellJS修好?:)

作者简介

本文最初由Bert Belder发表在StrongLoop上。Bert Belder从2010年就开始做Node.js了,并且他还是libuv的主要编写者之一,Node.js就是在这个库上构建的。他除了是StrongLoop和Node核心的技术领导者,他正在做的特性还会让Node处于创新的最前沿,甚至是在1.0版出来之后。StrongLoop降低了在Node中开发APIs的难度,还添加了监测、集群化以及私有注册的支持等DevOps能力。

查看英文原文:What’s New in Node.js v0.12 – execSync: a Synchronous API for Child Processes 2014年3月12日

Some useful ffmpeg commands ( commandline video converting tool)

1. Converting MOV/MPEG/AVI/MP4 –> flv 
#ffmpeg -i input file output.flv

2. Convert and adjust the video file resolution to output file
# ffmpeg -i input.avi -s 500×500 output.flv

3. Converting 3GP –> FLV
#ffmpeg -i input.3gp -sameq -an output.flv

4. Converting MPEG –>3GP
#ffmpeg -i input.mpeg -ab 8.85k -acodec libamr_wb -ac 1 -ar 16000 -vcodec h263 -s qcif output.3gp

5. Converting WMV –> to MP3
#ffmpeg -i input.wmv output.mp3

6. Converting AMR –> MP3
#ffmpeg -i input.amr -ar 22050 output.mp3

7. Converting FLV –> MP4
# ffmpeg -i input.flv -ar 22050 output.mp4

Advanced flash supported conversion.

#ffmpeg -i input.flv -s 480×360 -vcodec libx264 -b 1900kb -flags +loop -cmp +chroma -me_range 16 -me_method hex -subq 5 -i_qfactor 0.71 -qcomp 0.6 -qdiff 4 -directpred 1 -flags2 +fastpskip -dts_delta_threshold 1 -acodec libfaac -ab 128000 output.mp4

This code will support to play in Iphone.

#ffmpeg -i 400b75e5081fca44d094.flv -s 320×240 -r 24 -b 200k -bt 240k -vcodec libx264 -vpre hq -coder 0 -bf 0 -flags2 -wpred-dct8x8 -level 13 -maxrate 768k -bufsize 3M -acodec libfaac -ac 2 -ar 48000 -ab 192k new_output_new1.mp4

8. Converting AAC –> Mp3
#ffmpeg -i input.aac -ar 22050 -ab 32 output.mp3

Use ffmpeg with it’s best performance

The following arguments helps you to optimize the ffmpeg conversion to get the best result of converting mp4. to flv

# ffmpeg -i input.mp4 -ar 22050 -ab 56 -acodec mp3 -r 25 -f flv -b 400 -s 320×240 output.flv

-i = specify input file
-ar = audio sample rate
-ab = audio bitrate
-acodec = audio codec
-r = framerate
-f = output format
-b = bitrate (of video!)
-s = resize to width x height

10, Convert Video –> JPG Sequence
#ffmpeg -i input.mpg -an -r 10 -y -s 320×240 video%d.jpg

11. Convert Every n seconds to JPEG
#ffmpeg -i input.mpg -r 0.2 -sameq -f image2 thumbs%02d.jpg where r is the time when jpg file created. r can be 0.2 indicate every 5 second, if you need a jpeg on every 45 seconds use 1/45.

11. Crop the video between the specified time
#ffmpeg -i input.mpg -an -ss 00:00:03 -t 00:00:01 -r 1 -y -s 320×240 video%d.jpg where
-ss : Record start time
-t : No. of second to end suppose you want to crop 2 minutes video which starts from the 10 minutes play
-ss 00:10:00 -t 00:02:00
%d : Naming with timestamp

12. Converting flv –> mp3
#ffmpeg -i input.flv -vn -acodec copy output.mp3

13. Converting WAV –> MP3 
#ffmpeg -i Input.wav -ab 128 Output.mp3
#ffmpeg -i input.avi -vn -ar 44100 -ac 2 -ab 192 -f mp3 output.mp3

14 : Encode a video sequence for the iPpod/iPhone 
ffmpeg -i input.avi input -acodec aac -ab 128kb -vcodec mpeg4 -b 1200kb -mbd 2 -flags +4mv+trell -aic 2 -cmp 2 -subcmp 2 -s 320×180 -title X output.mp4

15. Converting AVI –> GIF
ffmpeg -i input.avi gif_anime.gif
16. Compress .avi –> divx
#ffmpeg -i input.avi -s 320×240 -vcodec msmpeg4v2 output.avi
Source : input.avi
Audio codec : aac
Audio bitrate : 128kb/s
Video codec : mpeg4
Video bitrate : 1200kb/s
Video size : 320px par 180px
Generated video : output.mp4

17. Converting flv –> Mp4
#ffmpeg -i sample.flv -ab 128kb -vcodec mpeg4 -b 1200kb -mbd 2 -s 320×240 final_video.mp4

some useful resources,

http://www.itbroadcastanddigitalcinema.com/ffmpeg_howto.html

http://ffmpeg.org/faq.html

SIEGE

Siege is an http load testing and benchmarking utility. It was designed to let web developers measure their code under duress, to see how it will stand up to load on the internet. Siege supports basic authentication, cookies, HTTP and HTTPS protocols. It lets its user hit a web server with a configurable number of simulated web browsers. Those browsers place the server “under siege.”

下载最新版

wget http://www.joedog.org/pub/siege/siege-latest.tar.gz

tar -zxf siege-lastest.tar.gz

cd siege-xxx

./configure && make && install

vi /tmp/tmpurl
http://127.0.0.1/index.html
http://127.0.0.1/images/banner/1.jpg
http://127.0.0.1/images/banner/8.jpg

siege -c 100 -b -i -r 100 -f /tmp/tmpurl

100个用户,执行100次。

** SIEGE 3.0.0
** Preparing 100 concurrent users for battle.
The server is now under siege.. done.

Transactions: 10000 hits
Availability: 100.00 %
Elapsed time: 2.44 secs
Data transferred: 1396.79 MB
Response time: 0.02 secs
Transaction rate: 4098.36 trans/sec
Throughput: 572.45 MB/sec
Concurrency: 91.24
Successful transactions: 10000
Failed transactions: 0
Longest transaction: 0.23
Shortest transaction: 0.00

Node.js 究竟是什么?

Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念。它的目标是帮助程序员构建高度可伸缩的应用程序,编写能够处理数万条同时连接到一个(只有一个)物理机的连接代码。

 

清单 2. Node 随机数字生成器
// these modules need to be imported in order to use them.
// Node has several modules. They are like any #include
// or import statement in other languages
var http = require(“http”);
var url = require(“url”);

// The most important line in any Node file. This function
// does the actual process of creating the server. Technically,
// Node tells the underlying operating system that whenever a
// connection is made, this particular callback function should be
// executed. Since we’re creating a web service with REST API,
// we want an HTTP server, which requires the http variable
// we created in the lines above.
// Finally, you can see that the callback method receives a ‘request’
// and ‘response’ object automatically. This should be familiar
// to any PHP or Java programmer.
http.createServer(function(request, response) {

// The response needs to handle all the headers, and the return codes
// These types of things are handled automatically in server programs
// like Apache and Tomcat, but Node requires everything to be done yourself
response.writeHead(200, {“Content-Type”: “text/plain”});

// Here is some unique-looking code. This is how Node retrives
// parameters passed in from client requests. The url module
// handles all these functions. The parse function
// deconstructs the URL, and places the query key-values in the
// query object. We can find the value for the “number” key
// by referencing it directly – the beauty of JavaScript.
var params = url.parse(request.url, true).query;
var input = params.number;

// These are the generic JavaScript methods that will create
// our random number that gets passed back to the caller
var numInput = new Number(input);
var numOutput = new Number(Math.random() * numInput).toFixed(0);

// Write the random number to response
response.write(numOutput);

// Node requires us to explicitly end this connection. This is because
// Node allows you to keep a connection open and pass data back and forth,
// though that advanced topic isn’t discussed in this article.
response.end();

// When we create the server, we have to explicitly connect the HTTP server to
// a port. Standard HTTP port is 80, so we’ll connect it to that one.
}).listen(80);

// Output a String to the console once the server starts up, letting us know everything
// starts up correctly
console.log(“Random Number Generator Running…”);

启动应用程序
将上面的代码放入一个名为 “random.js” 的文件中。现在,要启动这个应用程序并运行它(以便创建 HTTP 服务器并监听端口 80 上的连接),只需在您的命令提示中输入以下命令:% node random.js。下面是服务器已经启动并运行时看起来的样子:
root@ubuntu:/home/moila/ws/mike# node random.js
Random Number Generator Running…

访问应用程序
应用程序已经启动并运行。Node 正在监听所有连接,我们来测试一下。由于我们创建了一个简单的 RESTful API,所以可以使用 Web 浏览器来访问这个应用程序。键入以下地址(确保您已完成了上面的步骤):http://localhost/?number=27。
您的浏览器窗口将更改到一个介于 0 到 27 之间的随机数字。单击浏览器上的 “重新载入” 按钮,您会得到另一个随机数字。就是这样,这就是您的第一个 Node 应用程序!

 

学习

获得产品和技术

shell 上传目录

#!/bin/bash
updir=/root/wav
todir=/
sss=`find $updir -type d -printf $todir/’%P\n’| awk ‘{if ($0 == “”)next;print “mkdir ” $0}’`
aaa=`find $updir -type f -printf ‘put %p %P \n’`
ftp -nv spetechcular.com <<EOF
user quantong quantong2013
type binary
prompt
$sss
cd $todir
$aaa
quit
EOF

awk用法总结

awk 用法小结 – – – by ruson 2006.4 NTU

1. awk 非常适合于结构化的文本文件(行、列数据)复杂处理。相对于 sed 而言,它可进
行复杂的编程处理,并且可以产生复杂的报表输出。
2. awk 通常有三个版本,旧 awk、nawk(新) 、gawk。Solaris 下建议用 nawk,因为旧 awk
有很多功能不支持,例如数学运算幂 ^  ,函数getline,system等。
3. 基本语法:awk ‘pattern{action}’ filename   其中 action 内容可扩充,也可以有多个 action。
执行顺序:awk 一行行读入输入文件,顺序执行‘’内内容,按模式匹配来采取动作。
其他调用:awk 可用内部变量和函数,条件与循环语句,也可执行数学运算和字符串操
作。 此外, 可以使用 BEGIN和 END来执行处理前预操作和处理后后继操作。
A.  常用内部变量:NR(当前行数)NF(字段总数)$0(当前整行)$1(第一个记录)
FS(字段分隔符)OFS(输出字段分隔符)ORS(输出记录分隔符)
B.模式  pattern可以是/ /包含的匹配形式,也是条件语句如$3<10
C.BEGIN(处理文件前的 action,常包含 FS、OFS 等) 、END(处理文件后的 action)
D.条件与循环:if else(next,exit) ,for do while (continue,break)
E.数学运算符  + – * / % ^;数学函数 sin int;字符串函数 length index gsub substr等
F.数组与关联数组:a[1]; a[$1]; a[$0]; a[b[i]]
F.输出重定向和管道:>  >>    |  ;awk 内部命令:getline、system等
4.awk 的三种调用方式:  X awk ‘pattern{action}’ filename1,filename2
Y awk –f myscript.awk filename1,filename2
Z #!/bin/nawk –f … …  执行:myscript.awk filename
特别注意事项:

———————————————————————————————————————-
A.从 window拷贝语法句到 Unix 中,行结尾可能有不识别的字符会导致语法错误
B.写 script 文件时,BEGIN或 END后必须紧跟{
C.所有 action语句必须放在{ }中,否则提示语法错误。例如不可直接写 print
D.单独的赋值或 pattern条件句没有{ }则默认 print $0;例如{ }外面的 i=1
E.if条件块必须放在 action 中,也就是必须要有{ }来包含
F.条件的判断“相等”须用= =,而不是=(赋值) ;例如,if($1= =100)
G.输出多列须用“, ” (逗号)隔开;for 循环中间隔符为“; ”而不是“, ”
实例演练: (filename 为以下文件,注意:第二列用“-”隔开而非空格,以避免与 FS冲突)
ID   Name   Age   City  Country  Tel      Salary  Children
1001 Steven   25   NY   U.S.A  +01-02-323222   $4900   2
1002 Huang-Yu  30   BJ   CHN  +86-10-36789966    ¥6000   1
1003 Fish-Mad   27   SG   SG   +65-67456632    $3000   3
1004 Vale-Kiss   46   LD   ENG  +44-20-87634321   $6280   3
———————————————————————————————————————-
以下分基础实例:1.无 pattern  的 action 实例               2.有 pattern的 action 实例
3.BEGIN,END,FS,OFS 实例           4.if else; for while 循环实例
5.数学运算与字符串操作实例
高级实例:6.数组与关联数组运用实例               7.多文件运用 NR FNR实例
8.输出重定向和 getline实例
1

基   础   篇

1.无 pattern 的 action 实例
a.awk ‘{print NR $1 $NF}’ data.txt          打印行号,第一列和最后一列,中间无分隔符
b.awk ‘{print $1,$NF}’ data.txt            打印第一列和最后一列,并且中间有分隔符
c.awk ‘{print $0,$NF+10}’ data.txt          打印整行,并打印 最后一行加上 10 的结果
2.有 pattern 的 action 实例
a.awk ‘/[0-9]/’ data.txt                       打印记录中任意列包含数字 0-9 的行
b.awk ‘/01/||/02/’ data.txt                    打印包含 01 或者 02 的行
c.awk ‘/01/,/02/’ data.txt                   打印既包含01又包含02的行;等同awk ‘/01/&&/02’
d.awk ‘$1= =1001{print $2}’ data.txt      打印符合第一列等于 1001 的第二列
e.awk ‘$2= =”Steven”{print}’data.txt      打印符合第二列等于 Steven 的那些行
f.awk ‘$3>20&&$3<30’ data.txt           打印第三列在 20 到30 之间的那些行
g.nawk ‘$3*$NF<100’ data.txt           打印第三列和最后一列乘积小于 100 的那些行
h.awk ‘$6~/01/{print $2}’ data.txt         打印符合仅仅第六列里包含 01那些行的第二列
i.awk ‘NR>3{print $1,$2}’ data.txt          从第四行才开始打印第一列和第二列
3.有 BEGIN、END 并包含 FS、OFS 的实例
a.awk –F”+” ‘{print $1}’ data.txt             按+为分隔符来分隔列,并打印第一列
b.nawk –F’[+/t$]’ ‘{print $6,$7,$8,$9}’data.txt     按+或/t 或$都可作分隔符,并打印指定列
c.nawk ‘BEGIN{FS=”[/t+$]”}{print $6,$8,$9}’data.txt
按+,/t,$(顺序无所谓)为分割符,并打印指定列
d.nawk ‘BEGIN{FS=”[/t+$]”;OFS=”%”}{print $6,$7,$8,$9}’ data.txt
按+,/t,$为分割符, 用%作输出分隔符打印指定列
e.nawk –F‘[ [ ] ]’ ‘{print $1}’ data.txt          按 [ 或 ]  为分隔符,并打印第一列
f.nawk –F‘[ ][ ]’ ‘{print $1}’ data.txt            同上,按[  或 ] 为分隔符,并打印第一列
关于-F 和 BEGIN 内的 FS 定义特别注意如下:

A.-F 参数后紧跟单个分隔符,则用双引号“” ,例如 –F”+”
B.-F 参数后紧跟多个分隔符,则用单引号‘ ’并用[ ],中间顺序无所谓,例如-F’[+$]’
C.BEGIN 中的 FS无论是单个还是多个分隔,均用双引号“” ,多个则需加[ ]
例如:nawk ‘BEGIN{FS=”[/t+$]”}{print $6,$8,$9}’data.txt
D.BEGIN 中若同时有 FS和 OFS,则建议中间用分号“; ”来分隔开,否则提示出错
例如:nawk ‘BEGIN{FS=”[/t+$]”;OFS=”%”}{print $6,$7,$8,$9}’ data.txt
E.半方括号[ ]也可以作为分隔符,顺序无所谓。例如:-F‘[[]]’  或 –F‘[][]’
F.在用多个分隔符的时候,为避免语法错误或想得到正确的结果,最好用 nawk
4.条件 if else 和 for while 循环实例
a.nawk ‘{print($3>25 ? $2“ Old” : $2“ Young”)}’ data.txt
若第三列大于 25 就打印某某 Old;否则打印某某 Young
b.awk ‘{if($1>1002)print $2; else print $3}’ data.txt
若第二列大于 1002 就打印第二列,否则打印第三列
c.awk ‘NR>1{if($3<30)print$2;else if($3<40) print$2”m”;else exit;}END{print 10}’data.txt
从第二行开始判断第三列的值,如果小于 30 就打印$2,如果大于 30 而又小于
240,打印$2并后跟 m,若是都不符合就退出处理行,但是 END后的操作仍执行
d.awk ‘BEGIN{ORS=””}{for(i=1;i<NF-2;i++) print $i”/t”}{print “/n”}’ data.txt
打印出每行的前面几列,最后几列不打印。特别注意:默认情况下,print 每执
行一次时,另起一行打印。因此为避免每打印一列就重新一行,设置 ORS为空,
但是在每打印完符合条件的所有列后, 需要手工换行 (循环外的 print 起此作用) 。
e.awk ‘BEGIN{ORS=””}{i=1; while(i<NF-2){print $i”/t”; i++}}{print “/n”}’ data.txt
功能同上,打印出每行的前面几列,最后几列不打印。
5.数学运算和字符串操作实例
a.nawk ‘{print 2^5+sin(2.1)+int(0.9)}’ data.txt         在每一行都打印运算值(32.8632)
b.awk ‘END{print length(“How are you?”)}’ data.txt    打印出字符串的长度(12)
c.awk ‘END{print index(“How are you?”,”you”)}’ data.txt    返回 you在字符串中的开始位置(9)
d.nawk ‘{gsub(/ /$/,””);print $0}’ data.txt              把每行的$符号用空替掉,并打印行
e.awk ‘END{print substr(“How are you?”,9,3)}’ data.txt
从字符串的第九个位置开始截出后面 3 个长度的子字符串
f.nawk ‘{print toupper($2), tolower($2)}’ data.txt
分别打印第二列大写和小写
g.nawk ‘END{print match(“How are you you?”,/you/),RSTART,RLENGTH}’ data.txt
打印 you 在字符串中第一个匹配的位置以及长度(9,9,3)
h.nawk ‘END{str=”How are you doing?”;sub(/o/,”0”,str);print str}’ data.txt
将字符串变量指定字符中第一个符合含有 o 的用 0 替换调
特别注意:sub 函数的第三个参数不可直接用字符串,而必须用
字符串变量。
i.awk ‘END{print split(“Jan,Feb,Mar,Apr,May”,mymonths,”,”),mymonths[2]}’ data.txt
将字符串用第三个参数分隔符号进行分隔,把分隔的各个元素放
在第二个参数的数组中,函数返回分隔得到的元素数目。结果:
(5,Feb)

高   级   篇

6.数组与关联数组(a[1],a[$1] a[$0],a[b[i]])
a.awk ‘{for(i=1;i<NF;i++) {a[i]=$i; print a[i]}}’ data.txt     把文件每一列按行打印
b.awk ‘{a[$1]=$2}END{for(x in a) print a[x]}’ data.txt
数组 a 关联到第一列,并将第二列值赋给 a,最后打印 a 中的所有内容。
注意:但不是顺序打印。for中的 x是随意变量,awk 自动确定。
c.awk ‘{b[i]=$1;a[$1]=$2;i++}END{for(j=1;j<i;j++) print b[j],a[b[j]]}’ data.txt
实现从第二行开始打印每一行的第一列和第二列的功能。
注意:i 从0 开始取值,而 j 从1 开始。a 为关联数组,b 为顺序数组。
7.多输入文件和 NR、FNR 的实例
a. awk ‘BEGIN{OFS=FS=”:”} NR==FNR{a[$1]=$2} NR>FNR{$2=a[$1];print}’
/etc/shadow  /etc/passwd

该语句中第一个模式匹配到第一个输入文件 shadow, 第二个模式匹配到第二个输入
文件 passwd,并使用关联数组,实现不同文件关联列的其他列值相互替换。
3
A.awk 对多输入文件的执行顺序是,先将代码作用于第一个文件(一行行读入) ,然
后该重复的代码又作用于第二个文件,再作用于第三个文件。
B.awk 对多输入文件的执行顺序产生了行序号的问题。当第一个文件执行完,下次读
入第二个文件,那么第二个文件的第一行怎么算呢?如果又计为 1 的话,那不就两
个 1 了么?(因为第一个文件也有第一行) 。这就是 NR 和 FNR 的问题。
NR :全局行数(第二个文件的第一行接着第一个文件尾行数顺序计数)
FNR:当前文件自身的行数(不考虑前几个输入文件的自身行数及总数)
例如:data1.txt 中有40 行,data2.txt 中有 50 行,那么 awk ‘{}’ data1.txt data2.txt
NR   的值依次为:1,2……40,41,42……90
FNR 的值依次为:1,2……40, 1, 2……50
8.重定向输出和特别函数 getline 实例
a.awk ‘{print FILENAME,$0}’ data1.txt data2.txt >data_all.txt
把第一个文件和第二个文件合并到 data_all.txt 中,新文件第一列为原始文件名,后
面列为原始文件内容。
b.awk ‘$1!=fd{close(fd);fd=$1} {print substr($0,index($0,“ ”)+1)>$1}’ data_all.txt
把合并后的新文件 data.txt 重新拆开成原来的两个子文件,依照新文件的第一列
来产生新文件名。生成一个完整子文件后,关闭之;再生成下一个子文件。
A.getline 从整体上来说,应这么理解它的用法:
当其左右无重定向符 |  或 <  时,getline 作用于当前文件,读入当前文件的第一行给
其后跟的变量 var  或$0(无变量) ;应该注意到,由于 awk 在处理 getline
之前已经读入了一行,所以 getline得到的返回结果是隔行的。
当其左右有重定向符 |  或 <  时,getline 则作用于定向输入文件,由于该文件是刚打
开,并没有被 awk 读入一行,只是 getline 读入,那么 getline返回的是该文
件的第一行,而不是隔行。
B.getline 用法大致可分为三大类(每大类又分两小类) ,即总共有 6 种用法。代码如下:
nawk ‘BEGIN{“cat data.txt”|getline d; print d}’ data2.txt
nawk ‘BEGIN{“cat data.txt”|getline; print $0}’ data2.txt
nawk ‘BEGIN{getline d < “data.txt”; print d}’ data2.txt
nawk ‘BEGIN{getline < “data.txt”; print $0}’ data2.txt
以上四行代码均实现“只打印 data.txt文件的第一行” (若打印全部行,用循环)
eg. nawk ‘BEGIN{FS=”:”;while(getline<”/etc/passwd”>0){print $1}}’ data.txt
nawk ‘{getline d; print d”#”$3}’ data.txt
awk首先读入第一行,接着处理getline函数,然后把下一行指定给变量d,再先打印
d,由于d后面有换行符,所以后面紧跟的#会覆盖d,后面的$3同样也会覆盖d。
nawk ‘{getline; print $0”#”$3}’ data.txt
awk 首先读入第一行接着处理 getline 函数,然后把下一行指定给$0,现在的$0 已经
是下一行内容,后面的#和$3(从$0中取)会覆盖$0的内容。
c.nawk ‘BEGIN{system(“echo /”input your name:/” ”);getline var; print “/nYour name  is”,d,”/n”}’
系统提示输入名字,然后将输入的名字打印出来。特别注意:该 awk 语句后没
有输入文件名,而是利用键盘输入作为文件名。
4

经  典  实  例

1.问题描述
有如下银行帐单部分文本,
200000000000007|shi yan city qi pei bu
202111320000018|hospital
200000000000007|shiyan city renmen road qi bei bu
201602520002941|middle school
200000000000007|mingfeng road qi pei
201602120000113|zhuanghuang factory
201602320000115|liangyou factory
要求:将第一列中重复的合并为一行,其第二列填入最长地址的那列
得到的结果应为:
200000000000007|shiyan city renmen road qi bei bu
202111320000018|hospital
201602520002941|middle school
201602120000113|zhuanghuang factory
201602320000115|liangyou factory
代码: (假设下面代码在文件 myawk..sh 中)

#!/usr/bin/nawk -f

BEGIN{FS=OFS=”|”; i=1;}
{  if(a[$1]==0){b[i]=$1;a[$1]=$2;i++}
if(length(a[$1])<length($2)){a[$1]=$2}
}
END{for(j=1;j<i;j++) print b[j],a[b[j]]
}
执行:myawk.sh data.txt

比较代码: (实现不全)

awk ‘BEGIN{FS=OFS=”|”} !(length(a[$1])>length($2)){a[$1]=$2}
END{for(i in a)print i,a[i]}’   data.txt

解释:此例中,用了两个数组,a 用来与$1 关联,b 用来顺序记录,使得在最后打印时
是完全按照$1 顺序打印。条件句首先判断数组元素是否是第一次写入,若非,则
比较当前$2值和以前储存的值长度。
功能不全代码不能顺序打印。当$1 有重复,而$2 长度第一次、第二次、第三次是
以递减的方式时,该代码应用得较好。但是,当$2 各次得到的长度不确定时,代
码不能实现上述功能。例如:本例中第 5 行的第二列若比第 3 行的第二列长度长
时,功能不全代码就不能实现要求。
5
2.问题描述:
有两个文件如下:

data1 文件内容:
1   0.5   100
10   15    36.5
data2 文件内容:
50   10    19
3.2   1    5
要求:得到一个新的文件,内容是 data1 和 data2 对应的列数字相加的和,新文件内容:
51  10.5   119
13.2  16    41.5
代码: (假设下面代码在文件 myawk..sh 中)

#!/usr/bin/nawk -f

{  for(i=1;i<=NF;i++) a[i]=$i;
getline < “data2.txt”
for(j=1;j<NF;j++) printf $j+a[j] “/t”
printf $NF+a[NF]“/n”
}
执行:myawk.sh data1.txt
解释:   上述代码用到了getline同时读入第二个文件的行内容并存入到$0中, 最后用printf
来实现相加后的打印。注意后面同时紧跟打印了/t 和/n,以用来列之间的分隔和
行之间的分隔。此外,也可以用 print来实现,但是 print 每执行完一次都要换行,
(当然可以用 OFS 来进一步处理) 。
实际上也可以用另外一种办法来实现,就是用 NR、FNR 比较,然后分别将两个
文件赋值给不同的数组,然后相加。当然代码就没有上述代码简练。

3.问题描述
有两个如下文件:

data2.txt  文件内容如下:
01 1111  AAA  WW001  $$$$  1000.00
02 2222  BBB  GG001  %%%%  2000.00
03 3333  CCC  JJ001  ****  3000.00
04 4444  DDD  FF002  &&&&  4000.00
05 5555  EEE  RR002  @@@@  5000.00
06 666   FFF  UU003  JJJJ  6000.00
07 777   III  II005  PPPP  7000.00
08 8888  TTT  TT008  TTTT  8000.00
data1.txt  文件内容如下:
AAA  001  1000.00
BBB  001  2000.00
DDD  002  4000.00
EEE  002  5000.00
FFF  003  6000.00
data1 的第 1列、最后一列和 data2 的第 3 列、最后一列是相同的,
data1 的第 2列和 data2 的第 4 列的后3 位是相同的。
要求:data2中第三列、第四列后 3位、第六列完全和 data1相同的取出来得到新文件如
下内容:
6
01 1111  AAA  WW001  $$$$  1000.00
02 2222  BBB  GG001  %%%%  2000.00
04 4444  DDD  FF002  &&&&  4000.00
05 5555  EEE  RR002  @@@@  5000.00
06 666   FFF  UU003  JJJJ  6000.00
代码:

nawk ‘NR<=FNR {a[$1]=$1″x”$2″x”$3}
NR>FNR  { b=substr($4,3);
c=$3″x”b”x”$6;
if(c==a[$3]) print}’ data1.txt   data2.txt
执行:直接执行上述代码
解释:本例巧妙地利用了组合字符串(用 x 来组合) ,然后用来比较。
当 NR<=FNR 时,处理第一个文件,当 NR>FNR 时,处理第二个文件。