libvert开启TCP监听

1.设置libvirtd

编辑/etc/libvirt/libvirtd.conf

listen_tls = 0
listen_tcp = 1
auth_tcp="none"
tcp_port = "16509"

2.设置服务为监听状态

即使设置了listen_tcp也不会开启监听服务, 重启libvirt-bin服务,验证:

sudo netstat -nlpt 

# 可见16509端口并没有开启

ps aux | grep libvirt

# 可见libvirtd没有-l参数

需要开启监听服务,设置/etc/init/libvirt-bin.conf文件,设置exec /usr/sbin/libvirtd $libvirtd_opts -l,注意后面的-l选项 不能直接写在libvirtd_opts上,不生晓,原因不明

3. 验证

重启libvirt-bin服务, 使用netstat是否开启了tcp端口和ps查看libvirtd是否有-l选项,都没有问题后,运行:

virsh --connect qemu+tcp://node1/system list

其中node1为主机名,如果无错误,则表示正常开启tcp监听服务.

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

jekyll python命令行工具

jekyllclient

An easy jekyllclient to manager your posts in your local host.

How to use

That's easy to use once you configure it :) !

All the configure items are in the conf/blog.conf and it easy to configure ! If you change the location of this config file, you need to set JEKYLL_CONF environment variable as follows:

export JEKYLL_CONF=path/to/yourconf

All your config items should be in site section as follows:

[site]
base = <the root path of your blog>
posts = <the posts path, default '_posts'>
username = <your usename>

Once you finish the work above, Let's go!

Don't know how to work ? Run './blog help' to show help messages:

usage: blog [--version] [--debug] <subcommand> ...

A shell to manager blog

positional arguments:
  <subcommand>
    create         Create a new post.
    delete         Delete specified post.
    list           List all the posts.
    ls             Equivalent to list.
    show           Read a Post
    bash-completion
    help           Display help about this program or one of its subcomands.

optional arguments:
  --version        show program's version number and exit
  --debug          Print debugging output

See "blog help COMMAND" for help on a specific command.

Just as shown above, you can run blog help COMMAND for help on a specific command.

Want to list all your posts ? Just run ./blog list:

+-------------------------------+----------+------------+
| title                         | filetype | date       |
+-------------------------------+----------+------------+
| scriptnote                    | markdown | 2015-04-26 |
| HowToInstallJekyll            | markdown | 2015-04-26 |
| java-concurrency              | markdown | 2014-09-20 |
+-------------------------------+----------+------------+

A Pretty table ? Thanks to python prettytab.

If you want to show more details on the posts, run ./blog list -d:

+---------------------------------+------------+----------+--------+------------------------------+----------+----------+
| title                           | date       | category | layout | tags                         | filetype | comments |
+---------------------------------+------------+----------+--------+------------------------------+----------+----------+
| HelloWorld1                     | 2015-03-18 | linux    | post   | bash                         | markdown | true     |
| HelloWrold2                     | 2014-11-30 | linux    | post   | c                            | markdown | true     |
+---------------------------------+------------+----------+--------+------------------------------+----------+----------+

You'd like to show the contend of specified post ? Just run ./blog show -t HelloWorld1.

You can also set your style to read the post, choice from cat, less, more styles.

Once you get a new fresh idea and want to write down to your blog, run blog create, this smart script will set your metedata automatically, and call your editor depend on your EDITOR environment

Let's record our life by jekyll from now!

Issure & PR

Yes, welcome!

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

openstack java sdk开发包

What's openstack ?

OpenStack是一个云平台管理的项目,由几个主要的组件组合起来,旨在为公共及私有云的建设与管理提供平台。它是由 Rackspace 和 NASA 共同开发的云计算平台,帮助服务商和企业内部实现类似于 Amazon EC2 和 S3 的云基础架构服务(Infrastructure as a Service, IaaS),具体查看openstack官网

About this project

这个项目旨在写一个方便调用、方便扩展的openstack开发包。它是根据openstack api封装的java开发库,最初应实验室需求而开发。目前已经花了陆陆续续近3个月的时间,仅仅实现了基本功能,还有很多bug,以及功能尚未实现。

项目地址:https://github.com/krystism/openstack-java-sdk

How to use ?

首先使用maven构建本项目:

mvn package

如果需要把依赖包一块打进一个整体包,使用一下命令:

mvn assembly:assembly

项目运行需要配置文件,配置文件路径由系统变量OPENSTACK_CONF_PATH指定,默认为/etc/openstack,参考配置文件说明 我学习了openstack官方python库的设计架构,尽力做到调用简单,方便.以下是demo:

    OpenstackSession session = OpenstackSession.getSession("username", "password");// get session
    Nova nova = session.getNovaClient(); // get nova client
    // get a flavor list, print their name
    for (Flavor flavor : nova.flavors.list()) {
        System.out.println(flavor.getName());
    }
    // create a new server
    Server server = new Server();
    server.setName("demo");
    server.setImageRef("imageId");
    server.setFlavorRef("flavorId");
    // some other config 
    nova.servers.create(server); // call create method to execute.

Join me !

由于时间有限,加上本人代码功底尚浅,需要完美完成所有功能实在是感觉力不从心。希望有更多的大牛能够加入一起完成,并且指出我目前工作的不足,甚至重构整个代码,我真诚的感谢每一位热心的朋友!

下面讲讲我目前如何扩展新功能:

Step 1:创建model

model就是实体对应的java bean,接收请求过来的数据一般是json,即要把json表示的对象转化成的java对象。你可以完全由自己来定义自己的bean,我的所有bean都继承AbstractEntity,属性由Property注解,构造方法传递一个JSONObject对象,一般直接调用基类的构造方法就能完成JSONObject到java bean的转化。以下是model demo:

@Entity("volume_type")
public class VolumeType extends AbstractEntity {
    private static final long serialVersionUID = -6539238104579991330L;
    @Property("extra_specs")
    private JSONObject metadata;
    /*
    @Property("name")
    private String name;
    @Property("id")
    private String id;
    */
    public VolumeType() {
        super();
    }
    public VolumeType(JSONObject jsonObj) {
        super(jsonObj);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    // some other getter and setter here
}

Step 2:创建bean管理接口

管理接口即对bean定义操作,这些操作可能根据api的版本不同有不同的实现。在设计接口时,我没有使用共同接口,也尚未使用接口继承,原因是很多实体bean对应的操作差异性很大,即使是相同的操作,参数也不完全相同。下面是一个管理接口demo:

public interface ServerManager {
    /**
     * Get a server.
     * @param id ID of the Server to get.
     * @return Server
     * @throws OperationException
     */
    Server get(String id) throws OperationException;
    /**
     * Get a list of servers.
     * @return List of server
     * @throws OperationException
     */
    List<Server> list() throws OperationException;
    /**
     * Stop(power off) the server
     * @param id The id of server to stop.
     * @throws OperationException
     */
    void stop(String id) throws OperationException;
    /**
     * Start(power on) the server,
     * @param id The id of server to start.
     * @throws OperationException
     */
     void start(String id) throws OperationException;
     /**
      * Reboot a server, for a software-lever reboot
      * @param id The ID of server to reboot.
      * @see reboot(String id, boolean hard)
      */
     void reboot(String id) throws OperationException;
     /**
      * update the name for a Server
      * @param id the id of server to rename
      * @param name the new name of the server.
      * @throws OperationException
      */
     void rename(String id, String name) throws OperationException;
     /**
      * Create (boot) a new Server.<br/>
      * <i>Remember</i> : You must set name, imageRef, flavorRef !
      * @param instance The new server you have created.
      * @return
      * @throws OperationException
      */
     Server create(Server instance) throws OperationException;
     /**
      * Delete (i.e shut down and delete the image) this server.
      * @param id The ID of server to delete.
      * @throws OperationException
      */
     void delete(String id) throws OperationException;
}

Step 3: 实现管理接口

接下来就是具体实现接口,可能会根据api版本不同而有不同的实现,实际应用时可以根据配置文件指定需要使用的版本。下面是一个实现Demo:

public class Flavors extends AbstractManager<Flavor> implements FlavorManager{
    private final String PREFIX = "/flavors";
    public Flavors(Authenticated credentical) {
        super(credentical, Flavor.class);
    }
    /**
     * Get a list of all flavors
     * @return A List , which holds flavors
     * @throws OperationException
     */
    @Override
    public List<Flavor> list() throws OperationException {
        return _list(PREFIX + "/detail");
    }
    /**
     * Get a specific Flavor.
     * @param id The ID of Flavor to get. 
     * @return Flavor
     * @throws OperationException
     */
    @Override
    public Flavor get(String id) throws OperationException {
        return _get(PREFIX + "/" + id);
    }
    /**
     * Delete a specific Flavor.
     * @param id The ID of Flavor to delete.
     * @throws OperationException
     */
    @Override
    public void delete(String id) throws OperationException {
        _delete("/flavors/" + id);
    }
    /**
     * create a new flavor for a tenant
     * @param flavor The flavor to create
     * @return The new flavor
     * @throws OperationException
     */
    @Override
    public Flavor create(Flavor flavor) throws OperationException {
        return _create("/flavors", flavor);
    }
}

Step 4: 注册新功能

注册新功能就是把相应的管理接口添加到client下(比如Nova, Glance等),目前我直接硬编码,实际操作应该根据配置文件选择api版本由工厂负责创建,以下是demo:

public class Nova {
    public final FlavorManager flavors;
    public final HypervisorManager hypervisors;
    public final ServerManager servers;
    public final KeyPairManager keypairs;
    public Nova(Authenticated credentical) {
        // bad work, don't do that!!
        flavors = new Flavors(credentical);
        hypervisors = new Hypervisors(credentical);
        servers = new Servers(credentical);
        keypairs = new KeyPairs(credentical);
    }

How to extend new features?

如何为已经实现的接口增加新功能,比如在请求前记录日志,或者使用cache。只需要增加装饰器即可!以下是Demo:

public class FlavorCachedManager implements FlavorManager {
    private FlavorManager flavors;
    public FlavorCachedManager(FlavorManager flavors) {
        this.flavors = flavors;
    }
    @Override
    public Flavor get(String id) throws OperationException {
        Flavor flavor = getFromCache(id);
        if (flavor == null) {
            flavor = flavors.get(id);
        }
        addToCache(flavor);
        return flavor;
    }

}

Copyright

The MIT License (MIT)

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

Leetcode详细解答

最新代码:https://github.com/krystism/leetcode

Algorithms

Database

Shell

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

蓄水池抽样

什么是蓄水池抽样,它能解决什么问题?

从一次面试说起

百度面试以算法为主啊,手动写代码。第一道题是实现c语言库函数strcpy,这个原理很简单,但要注意以下这几点:

  • 空指针检查(包括src和dest)
  • 内存重叠,要检查指针是否重叠
  • 最后拷贝时,别忘了在dest追加字符串终结符号0
  • 如何保证dest已分配足够内存
  • 为什么从后向前拷贝?

第二道题是写一个类,实现堆的操作。说实话,虽然堆的操作不难,但要真正实现它并不容易。以下需要注意的点:

  • 泛型参数(泛化编程)
  • 类型必需可比较或者提供比较器
  • 不能实例泛型类型,即不能new T[]或者new T(),只能使用Object数组
  • 内存动态分配,内存拷贝(数组拷贝)

重点是第三道题目:给定一个文件,从中随机取出n行,并计算时间复杂度。我上来便是这样的代码:

import random
def sample(filename, n = 3):
    assert(filename is not None)
    result = []
    with open(filename) as f:
        lines = f.readlines()
    while len(result) < n :
        line = random.choice(lines)
        if line not in result:
            result.append(line.strip())
    return result

这种方法

  • 必须把文件内容全读入内存,如果文件很大怎么办?
  • 设N为文件行数,n和N接近时,越到后面,冲突越大,效率极低。
  • 有人说,先随机生成n个数构成一个集合A(还是有冲突哦),读取文件,当行数属于A时,取出该行,问题不就解决了? 问题是文件总行数是多少?必须知道文件总行数才能知道随机数的取值范围啊。必须先扫描一遍文件?文件很大时这样的效率如何?

后来面试官问我知不知道分治法,我说了解,但这有关系么?文件分割建索引?全错!!!

蓄水池抽样

蓄水池抽样(Reservoir Sampling )是一个很有趣的问题,它能够在o(n)时间内对n个数据进行等概率随机抽取, 例如:从1000个数据中等概率随机抽取出100个。另外,如果数据集合的量特别大或者还在增长(相当于未知数据集合总量), 该算法依然可以等概率抽样。

以上摘自handspeaker博客

算法步骤为:

  1. 从文件中取前n行,结果集result
  2. 令i表示当前行数,c为当前行内容,m = random(1, i),即m为1~i的一个随机数。
  3. 若m <= n, 则令result[m] = c,即替换第m行内容,否则舍弃c。
  4. 若已到文件结尾,退出算法,返回result,否则转2

利用归纳法可以证明每行被取的概率是相等的,证明过程 见handspeaker博客

回到问题

问题解决了,毫无悬念!

import random
def sample(filename, n = 5):
    assert(filename is not None)
    result = []
    with open(filename, mode = "r") as f:
        for i in range(n):
            line = f.readline()
            if line == '':
                return result
            else:
                result.append(line.strip())
        i = n
        for line in f:
            k = random.randint(0, i)
            if k < n:
                result[k] = line.strip()
            i += 1
    return result

 

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

康托展开及其应用

康托展开

康托展开是一个全排列到一个自然数的双射,常用于构建hash表时的空间压缩。

定义

公式为:

X = a[n - 1] * (n - 1)! + a[n - 2] * (n - 2)! + ... + a[0] * 0!,
其中, a[i]为整数,并且0 <= a[i] <= i, 0 <= i < n, 表示当前未出现的的元素
中排第几个。

比如31254,

  • 在3后面比3小的有2个,分别为1,2
  • 在1后面比1小的有0个
  • 在2后面比2小的有0个
  • 在5后面比5小的有1个,为4
  • 在4后面比4小的有0个

因此a数组序列为2 0 0 1 0

X = 2 * 4! + 0 * 3! + 0 * 2! + 1 * 1! + 0 * 0!
  = 2 * 24 + 1
  = 49

既然是双射关系那一定可以反推出来31254这个序列。 首先我们需要推出a序列。

  • 49 / 4! = 2,因此a[4] = 2, 此时49 % 4! = 1,
  • 1 / 3! = 1 / 2! = 0,因此a[3] = a[2] = 0,
  • 而 1 / 1 = 1, 因此a[1] = 1,1 % 1! = 0,
  • 0 / 0! = 0,因此a[0] = 0
  • 所以得到a数组为2 0 0 1 0

再由a数组推出序列,根据a数组的意义反推。

  • a[4] = 2, 表示它在1 2 3 4 5 序列中比它小的有2个,即它自己排第3,它等于3
  • a[3] = 0, 表示它在1 2 4 5序列中比它小的有0个,即最小数,等于1
  • a[2] = 0, 表示它在2 4 5 中最小,等于2
  • a[1] = 1, 表示它在4 5中比它小的有一个,即排第2,等于5
  • a[0] = 0, 表示它在4中最小,只能是4

因此序列为3 1 2 5 4

应用

一个直观的应用就是给定一个自然数集合和一个序列,求这个序列中按从小到大的顺序 排第几个?

比如1 2 3 4 5, 3 1 2 5 4比它小的序列有49个,即它排第50

另一个应用就是逆推第K个排列是多少,比如第50个全排列是多少?则首先减1得到49, 再反推即可得到3 1 2 5 4

另外在保存一个序列,我们可能需要开一个数组,如果能够把它映射成一个自然数, 则只需要保存一个整数,大大压缩空间.

计算

计算包括编码(根据序列求对应的自然数)和解码(康托展开)。

编码

static const int FAC[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int cantor(int *a, int n)
{
    assert(n < 10);
    int x = 0;
    for (int i = 0; i < n; ++i) {
        int smaller = 0;
        for (int j = i + 1; j < n; ++j) {
            if (a[j] < a[i])
                smaller++;
        }
        x += FAC[n - i - 1] * smaller;
    }
    return x;
}

解码

int decantor(int *a, int n, int k)
{
    int *num = malloc(sizeof(int) * n );
    int len = n;
    for (int i = 0; i < n; ++i)
        num[i] = i + 1;
    int cur = 0;
    for (int i = n - 1; i > 0; --i) {
        int index = k / FAC[i];
        k %= FAC[i];
        a[cur++] = num[index];
        listRemove(num, &len, index);
    }
    a[cur] = num[0];
    free(num);
    return 0;
}

 

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

减少qcow文件大小

 

当做虚拟机备份快照时,镜像的大小一般会大于实际数据大小,you'll need to zero out all free space of the partitions contained within the guest first.

参考维基百科:https://pve.proxmox.com/wiki/Shrin_Qcow2_Disk_Files

针对linux镜像:

1. 删除无用文件

尽量删除一些无用文件

2. Zero out磁盘

dd if=/dev/zero of=/mytempfile
# that could take a some time
rm -f /mytempfile

3.减少磁盘大小

备份

mv image.qcow2 image.qcow2_backup

#1: Shrink your disk without compression (better performance, larger disk size):

qemu-img convert -O qcow2 image.qcow2_backup image.qcow2

#2: Shrink your disk with compression (smaller disk size, takes longer to shrink, performance impact on slower systems):

qemu-img convert -O qcow2 -c image.qcow2_backup image.qcow2

 

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

nc命令官方的几个Demo实例

 

nc命令可用于发送任务tcp/udp连接和监听.

官方描述的主要功能包括:

  • simple TCP proxies
  • shell-script based HTTP clients and servers
  • network daemon testing
  • a SOCKS or HTTP ProxyCommand for ssh(1)
  • and much, much more

下面看看官方的几个例子:

1. p2p简单聊天工具

在A机器运行(假设A机器主机名为node1:

nc -l 1234 # -l表示监听

在B机器运行:

nc node1 1234

此时从A或者B机器输入任何信息,都会在对方的机器中回显,实现了简单的即时聊天工具.

2. 文件传输

假设B机器有一个文件data.txt,需要传输到A机器:

在A机器:

nc -l 1234 >data.txt # data.txt需要保存的目标文件名

在B机器:

nc node1 1234 <data.txt # data.txt需要传输的文件

3.远程操作(类似ssh)

假设B需要远程操作A,又没有安装ssh:

在A机器:

rm -f /tmp/f; mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f

在B机器:

nc node1 1234

4.发送HTTP请求

echo "GET / HTTP/1.0\r\n\r\n" | nc localhost 80

5.端口扫描

# 查看主机名为node1的80端口是否开放
nc -zv node1 80
# 扫描主机名为node1的1~1024哪些端口是开放的
nc -zc node1 1-1024

 

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

linux常用命令总结

1. 删除所有的换行符和空格符

sed  -e ':a;N;s/\n//;s/ //g;ba' test.txt

or

cat test.txt | tr -d '\n '

2. spark on hive

  • spark编译了hive
  • 必须把hive-site.xml 复制到spark配置目录中
  • 必须把hive使用的元数据库的驱动加入到SPARK_CLASSPATH中 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCe17+08pqcvLq16DX8ZklIYcYBVZBoodiWKyBZdK2d+iJvvzYfWi8kbuWhZT6H9cGeOn3VfBrdVAgVISSS0zjGvNzc1ndzxFwl/AcG7k2F8dt3KQiCSMXckCBO2nOhW9EcQU88NHlISUlXT5hacps0Gl/nhDeO9ayYRL+Kf40/gmtuSo3CcoFlxPin2Q3cxnCULjJjBVzLpXSnOoPqBf8BRh3Se8b4adHh6cIcvuwevbXzByalj3YC12KlSEM0vtC93CmD3YyQUV/kJuzZt4PwOM0YavI36m7grFvysZjnOCMESiF65nMH5gxgca/SpNkMWvttdDzI2/+FP99zMFPh bupt@controller

shell 笔记

1. 获取当前shell的环境变量,按行输出

xargs -0 或者 --null 表示分隔符为0字符, -n表示每次传参数的最大个数

cat /proc/$$/environ | xargs -0 -n 1
cat /proc/$$/environ | tr  '\0' '\n'

2. 设置动态库路径

export LD_LIBRARY_PATH=/opt/myapp/lib

3. let算术操作

支持 ++ -- + - * / ** & |

a=$((5 ** 5)) # a = 3125, 等价a = let 5 ** 5
echo "scale=3; 10 / 3" | bc # 浮点数

4. bash正则表达式匹配

[[ 'a5a' =~ [a-zA-Z][0-9][a-z] ]] && echo "YES" || echo "NO"
# 注意 =~ 后面的正则表达式不能用引号

5. 重定向

>& 实际复制了文件描述符, ls >dirlist 2>&1 与 ls 2>&1 >dirlist 不一样

6. 关联数组

  • declare -a a 把变量a声明为索引数组
  • declare -A a 把变量a声明为关联数组
  • ${a[@]}获取所有的值, ${!a[@]} 获取所有的键 ### 7. exec & source
  • source: 在当前进程中执行参数文件中的各个命令,而不是另起子进程
  • exec: 以当前命令替换shell的上下文,并不起子进程,使用这一命令时任何现有环境都将会被清除。 exec在对文件描述符进行操作的时候,也只有在这时,exec不会覆盖你当前的 shell 环境。 \(command1;command2\)\: 将命令置于新进程,继承父进程所有文件描述符

8. 关联数组

declare -A map
map[key]=value
map=([key1]=value1 [key2]=value2)
keyset: ${!map[@]}
values: ${map[@]}
map[count]=0
let map[count]++

9. tput stty

10. 通过引用子shell保留空格和回车,使用引号

out="$(ls)"

11. read -n 字符个数 -s 禁止回显 -p 提示符 -t 时间 -d 分隔符

12. true命令可能会生成一个新进程,使用冒号效率更高

13. 字段分隔符、参数分隔符IFS

IFS=','
line='1,2,3,4,5'
for i in line
do
 echo $i
done

14. for 循环

# 迭代
for i in list
do
    echo $i
done
# range
for i in {1..50}
do
    echo $i
done
# c 风格
for((i = 0; i <= 50; ++i))
do
    echo $i
done

15. cat

cat - a >out # 从标准输入流输入内容插入a中
cat -s 过滤多余空行

16. script & scriptreplay

17. find 命令

#删除所有的swp文件
find . -maxdepth 1 -type f -name "*.swp" -delete
# 将10天前的文件复制到OLD目录
find . -maxdepth 1 -type -f  -mtime +10 -name ".txt" -exec cp {} OLD \;

18. xargs 命令

echo -n "split:split:split:split" | xargs -d : -n 2
split split
split split
#output
split split
split split
# 统计c代码行数
find . -maxdepth 1 -type f -name ".c" -print0 | xargs -0 wc -l 
# 注意print0 和-0 表示以null作为分隔符,防止文件名包括空格回车造成错误

19. tr命令

# 小写转化大写
echo "heLLo" | tr 'a-z' 'A-Z'
echo "heLLo" | tr '[:lower:]' ''[:upper:]'
# 空格转化为回车
echo "1 2 3 4" | tr ' ' '\n'
# 删除数字
echo "abcd123dd" | tr -d '0-9' # abcddd
# 保留数字
echo "abcd123dd" | tr -d -c '0-9' # 123
# 压缩字符
echo "aaabbbccc" | tr -s 'ab' # abccc
# 求和
echo '1 2 3 4 5' | echo $[ $(tr ' ' '+') ]

20. 文件校验

# 产生校验
md5sum test.txt >test.md5
# 校验
md5sum -c test.md5

21. 文件加密crypt gpg base64

22. sort

# 默认按字典序排列
echo "3 2 1 13 11 12" |tr ' ' '\n' | sort | tr '\n' ' ' # 1 11 12 13 2 3
# 使用-n按大小排序
echo "3 2 1 13 11 12" |tr ' ' '\n' | sort -n | tr '\n' ' ' # 1 2 3 11 12 13
# 使用-r表示逆序
# 检查文件是否排序
sort -C test1 && echo "sorted" || echo "unsorted"
# 使用-k指定哪个列作为键
# -b 忽略前导空白行
# -m 把已排好序的文件归并

23. uniq

# 注意该文件必须保证是已排好序的文件
# 过滤重复行
echo "1 2 2 3 3 3" | tr ' ' '\n' | uniq # 1 2 3 
# 只输出唯一行
echo "1 2 2 3 3 3" | tr ' ' '\n' | uniq -u # 1
# 统计重复次数
echo "a b b c c c c" | tr ' ' '\n' | uniq -c # 1 a 2 b 4 c
# 输出重复行
echo "a b b c c c c" | tr ' ' '\n' | uniq -d # b c

24. mktemp 创建临时文件

25. 切分文件名

# 获取文件扩展名
${file#*.}
# 或者文件名
${file%.*}

26. 批量重名名文件

# 把*.JPG 重命名为*.jpg
rename *.JPG *.jpg
# 将文件名的空格替换为_
rename 's/ /_/g' *
# 转化文件大小写
rename 'y/a-z/A-Z/' *

27. look单词查找

28. 数组追加

a=() # 声明一个空数组
a+=(1 2) # 追加1 2 到数组a中

29. 并行进程加速命令执行

PIDS=()
for i in {1..50}
do
    echo $i >>out &
    PIDS+=("$!") # $!表示最后一个后台进程pid,追加到PIDS数组中
done
wait ${PIDS[@]}

30. 文件交集、差集

# 两个文件必须是排好序的
comm A.txt b.txt
# 第1列包含只在A文件(A的差集),2列包含只在B文件(B 的差集),
# 第3列包含A、B相同的行(A、B的交集)
# -1 -2 -3 分布表示删除第1,2,3列

31. 文件差异和修补

# 查看文件差异
diff a.txt b.txt
# 打补丁
diff a.txt b.txt >patch
patch a.txt < patch
# 取消补丁
patch -p1 a.txt <patch
# 生成目录
diff -Naur d1 d2
# -r 递归 -N:缺失文件视为空文件 -u:生成一体化输出 -a 将所有文件视为文本文件

32. head & tail

head -n num
# num 为正数,则只输出前num行,默认为10,若num为负数,则输出前num行以外的行
tail -n num
tail -f file
#当进程PID停止,tail自动退出
tail -f  --pid $PID file

33. 只列出目录的方法

ls -d */ # 不能少/
ls -F | grep "/$"
ls -l | grep "^d"
find . -maxdepth 1 -type d -print

34. grep

# -o 只输出匹配的文本部分
# -c 统计匹配行数(不是次数)
# 求匹配次数
grep -o '[0-9]+' | wc -l
# 打印行号 -n
# -b打印偏移量,常常和-o连用
# -l 只打印匹配的文件列表,-L打印不匹配的文件列表
# -R 递归
# -i 忽略大小写
# 匹配多个样式, -e
grep -e 'pattern1' -e 'pattern2'
# 指定文件
# 只搜索c或者cpp文件
grep --include *.{c,cpp} 
# --exclude "README.md" 不搜索该文件
# -Z 输出以0作为文件名终结符,与-l结合使用
grep -Zlr "test" * 
# -q 不输出任何东西,匹配返回0,不匹配返回1
# -A -B -C 输出上下文-A向后输出n行,-B向前输出n行,-C 向前向后输出n行

35. cut

# -f 指定列, 与--complement结合,输出不包括这些列的所有列 -f 3,5打印第3,5列
# -f 3- 打印从第3列开始的所有列
# -c字符 -b字节 -f字段

36. sed

37. awk

# -v 传递外部变量
# getline读取一行,尤其在BEGIN块使用过滤头部信息
# getline var,var保存内容,若调用不带参数的getline,则可以使用$0-$9访问
# -F列分隔符

 

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

bash数组总结

 

bash支持两种数组,一种是索引数组,一种是关联数组

索引数组

数组的值类型是任意的,索引也未必一定要连续,当做列表理解更好

下面总结下索引数组,即列表:

1. 声明

declare -a a

2. 初始化

a=(1 2 3 4)
# OR
a=([0]=2 [3]=8) # 注意长度为2,不是4

3. 获取列表长度

size=${a[@]}

4. 追加元素

a+=(11 12 13 14)

5. 赋值

a[1]=9

6. 按索引读取

value=${a[0]} # 读取索引0的值

7. 删除某元素

unset a[0]

8. 清空数组

unset a

9. 切片

echo ${a[@]:1:3} # 从索引1开始的3个元素
# 也支持负数索引,-1表示最后一个,但负数必须用括号括住
last=${a[@]:(-1):1}

10. 遍历

for i in ${a[@]}
do
    echo $i
done

关联数组

1. 声明

declare -A map

2. 初始化

map[key1]=value1
map[key2]=value2
# or
map=([key1]=value1 [key2]=value2)

3. 长度

size=${!map[@]}

4. 获取键集合

keyset=${!map[@]}

5. 获取值集合

values=${map[@]}

6. 遍历

for key in ${!map[$@]}
do
    echo $key:${map[$key]}
done

 

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!