几个常用的 Linux 操作: grep、find、xargs、sed

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q1075355798/article/details/80524717

摘要

数据库有“增、删、查、改”几个动作,而在 Linux 下生活的人,莫外乎也经常有这几个操作。

找文件

在指定目录下找文件,常用 find 命令。以下是 man 手册对 find 命令进行功能性的解释:

find - search for files in a directory hierarchy

比如,要去 kernel/driver/ 目录下找一个名字叫 led-class.c 文件:

$ find ./kernel/msm-3.18/drivers/ -name  led-class.c
./kernel/msm-3.18/drivers/leds/led-class.c

或者找到所有头文件(以 .h 结尾的文件)

find ./kernel/msm-3.18/drivers/ -name *.h

这样,就可以找到 kernel/msm-3.18/drivers/ 目录下所有的头文件了(* 表示通配符,意思是匹配所有以 .h 结尾的文件)。

找字符串

要找一个文件或者多个文件里面某一个指定的字符串,常用 grep 命令。比如找出 kernel/msm-3.18/drivers/leds/led-class.c 文件中所有的 “leds_class”字符串:

$ grep  -rsn "leds_class" kernel/msm-3.18/drivers/leds/led-class.c
25:static struct class *leds_class;
224:static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume);
233:    led_cdev->dev = device_create_with_groups(leds_class, parent, 0,
303:    leds_class = class_create(THIS_MODULE, "leds");
304:    if (IS_ERR(leds_class))
305:        return PTR_ERR(leds_class);
306:    leds_class->pm = &leds_class_dev_pm_ops;
307:    leds_class->dev_groups = led_groups;
313:    class_destroy(leds_class);

上面即可列出,leds_class 这个字符串,分别在该文件的第 25、224、233、303、304、305、306、307、313 行出现。

现在是找 leds_class 这个字符串在 led-class.c 文件中出现的位置。那现在换一个场景,找 leds_class 这个字符串出现在哪些文件中,可以使用如下方式:

$ find ./kernel/msm-3.18/drivers/ -name *.c | xargs grep leds_class  
./kernel/msm-3.18/drivers/leds/led-class.c:static struct class *leds_class;
./kernel/msm-3.18/drivers/leds/led-class.c:static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume);
./kernel/msm-3.18/drivers/leds/led-class.c: led_cdev->dev = device_create_with_groups(leds_class, parent, 0,
./kernel/msm-3.18/drivers/leds/led-class.c: leds_class = class_create(THIS_MODULE, "leds");
./kernel/msm-3.18/drivers/leds/led-class.c: if (IS_ERR(leds_class))
./kernel/msm-3.18/drivers/leds/led-class.c:     return PTR_ERR(leds_class);
./kernel/msm-3.18/drivers/leds/led-class.c: leds_class->pm = &leds_class_dev_pm_ops;
./kernel/msm-3.18/drivers/leds/led-class.c: leds_class->dev_groups = led_groups;
./kernel/msm-3.18/drivers/leds/led-class.c: class_destroy(leds_class);

不过这个方式,个人认为比较鸡肋,还不如直接这样:

grep -rn leds_class ./kernel/msm-3.18/drivers/

找到某个文件,并删除它

其实这个就是两个或者多个命令的组合,前一个命令的输出是后一个命令的输入,这个传递过程中,需要一个媒介来将前一个命令的输出,传递到后一个命令的输入。此时使用 xargs 可以解决这个问题。比如,找到 led-class.c 文件并删除它,我们常规的两个命令操作如下:

$ find ./kernel/msm-3.18/drivers/ -name  led-class.c
./kernel/msm-3.18/drivers/leds/led-class.c
$ rm -rf ./kernel/msm-3.18/drivers/leds/led-class.c

但如果想偷懒,一步到位呢?使用 xargs 就可以达到该要求:

$ find ./kernel/msm-3.18/drivers/ -name  led-class.c | xargs rm -rf
$ git status ./kernel/msm-3.18/drivers/
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    deleted:    kernel/msm-3.18/drivers/leds/led-class.c

no changes added to commit (use "git add" and/or "git commit -a")

确认是已经删除了。(当然,没事别随意删除,尤其是在没有版本控制或者备份的情况下^_^)

批量替换

比如将某个目录及其子目录下的 N 个文件中的字符串 A 替换成字符串 B,使用 sed 可以顺利完成。比如将 frameworks/ 目录下所有文件中的 leds 字符串替换成 sdel 字符串。先列一下有哪些文件:

$ grep  -rn leds ./frameworks/
./frameworks/native/cmds/dumpstate/dumpstate.cpp:915:    dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
./frameworks/native/cmds/dumpstate/dumpstate.cpp:917:    dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
./frameworks/native/cmds/dumpstate/dumpstate.cpp:919:    dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
./frameworks/native/cmds/dumpstate/dumpstate.cpp:921:    dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
./frameworks/native/cmds/dumpstate/dumpstate.cpp:923:    dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
./frameworks/native/services/inputflinger/tests/InputReader_test.cpp:325:        KeyedVector<int32_t, bool> leds;
./frameworks/native/services/inputflinger/tests/InputReader_test.cpp:431:        device->leds.add(led, initialState);
./frameworks/native/services/inputflinger/tests/InputReader_test.cpp:436:        return device->leds.valueFor(led);
./frameworks/native/services/inputflinger/tests/InputReader_test.cpp:658:        return device && device->leds.indexOfKey(led) >= 0;
./frameworks/native/services/inputflinger/tests/InputReader_test.cpp:664:            ssize_t index = device->leds.indexOfKey(led);
./frameworks/native/services/inputflinger/tests/InputReader_test.cpp:666:                device->leds.replaceValueAt(led, on);
./frameworks/base/tests/StatusBar/src/com/android/statusbartest/ToastTest.java:87:                String text = "freq=" + readFile("/sys/class/leds/red/device/grpfreq")
./frameworks/base/tests/StatusBar/src/com/android/statusbartest/ToastTest.java:88:                        + "\npwm=" + readFile("/sys/class/leds/red/device/grppwm");

开始替换吧:

$ sed -i 's/leds/sedl/g' `grep  -lrn leds ./frameworks/`

注意,前面是单引号(’ ‘),后面是键盘波浪线(~)位置的斜点(`)。
看一下其中一个文件的修改点:

--- a/frameworks/base/tests/StatusBar/src/com/android/statusbartest/ToastTest.java
+++ b/frameworks/base/tests/StatusBar/src/com/android/statusbartest/ToastTest.java
@@ -84,8 +84,8 @@ public class ToastTest extends TestActivity
         new Test("Read lights") {
             public void run()
             {
-                String text = "freq=" + readFile("/sys/class/leds/red/device/grpfreq")
-                        + "\npwm=" + readFile("/sys/class/leds/red/device/grppwm");
+                String text = "freq=" + readFile("/sys/class/sedl/red/device/grpfreq")
+                        + "\npwm=" + readFile("/sys/class/sedl/red/device/grppwm");
                 mToast1 = Toast.makeText(ToastTest.this, text, Toast.LENGTH_SHORT);
                 mToast1.show();
             }

已经将 leds 修改为 ldes 了。下面对 s/leds/sedl/g 稍作解释:

s/原字符串/目的字符串/全局替换

这个方法在 vim 里面也可以使用的。

哎,蛋疼!

猜你喜欢

转载自blog.csdn.net/q1075355798/article/details/80524717