【问题标题】:Bash: Move specific line of content in file to the top of the fileBash:将文件中的特定内容行移动到文件顶部
【发布时间】:2021-07-05 22:07:04
【问题描述】:

我正在制作一个脚本(在 vim 中),它会遍历一个文件并查找特定的行。如果该行匹配,我希望将其移至文件顶部。

文件看起来像这样:

6596628c9cbab49b80d6a07d0304377768f5114e7f8b21edffa820aab1c508be, ./favicon.ico
150a04dd76f733e5ef05ece49de115d05f71efa8e73025e015dd4e0fb3217553, ./about.php
28acfc4b0d378c22a2c0e4913cae3d15aef9b21938de81be92f74aef85b0cc0e, ./info.php
67976bbbd1b62a00d454da3a9f95e72d97d0fd156d4c65a12707f2602cbea582, ./missing.php
6ed318718f4cc617c82121db7cde54188eac6f89c355f0bfe9d198218de7fffc, ./browse.php
abd277cc3453be980bb48cbffe9d1f7422ca1ef4bc0b7d035fda87cea4d55cbc, ./composer.phar
73ac79eccac12120dc601cd6cce1282a1d8a920d440d3d1141d257db1ed4b0f0, ./search.php
f412aabd74f4c99bd32c5e534132c565f52c2bd32fbf7f629eb5a4495ac46351, ./index.php
c2d49a4873088fbe635d8653494f7f1425b6ad9f55d63ee4de52170d8a8d01b8, ./content/style.css
18e7d61367d80bc125b309ac002bb3946c5e7ba419ef59537afc939eff799dfd, ./content/logo.png
d8da15f62d55641320f7e7c21d9be86db6d81f7667bbd35c738b4c917cad3ce9, ./robots.txt

如何将第 8 行 (index.php) 上的内容移动到顶部,使其看起来像这样:

f412aabd74f4c99bd32c5e534132c565f52c2bd32fbf7f629eb5a4495ac46351, ./index.php
6596628c9cbab49b80d6a07d0304377768f5114e7f8b21edffa820aab1c508be, ./favicon.ico
150a04dd76f733e5ef05ece49de115d05f71efa8e73025e015dd4e0fb3217553, ./about.php
28acfc4b0d378c22a2c0e4913cae3d15aef9b21938de81be92f74aef85b0cc0e, ./info.php
67976bbbd1b62a00d454da3a9f95e72d97d0fd156d4c65a12707f2602cbea582, ./missing.php
6ed318718f4cc617c82121db7cde54188eac6f89c355f0bfe9d198218de7fffc, ./browse.php
abd277cc3453be980bb48cbffe9d1f7422ca1ef4bc0b7d035fda87cea4d55cbc, ./composer.phar
73ac79eccac12120dc601cd6cce1282a1d8a920d440d3d1141d257db1ed4b0f0, ./search.php
c2d49a4873088fbe635d8653494f7f1425b6ad9f55d63ee4de52170d8a8d01b8, ./content/style.css
18e7d61367d80bc125b309ac002bb3946c5e7ba419ef59537afc939eff799dfd, ./content/logo.png
d8da15f62d55641320f7e7c21d9be86db6d81f7667bbd35c738b4c917cad3ce9, ./robots.txt

(该文件包含大约 9000 行)

如何才能最有效地做到这一点?

【问题讨论】:

  • 如果你使用 vim,为什么不用 :8m0 呢?如果行号不固定,请使用:/index\.php/m0
  • @Sundeep 嗯,不完全是,这就是为什么在 vim 中很难用谷歌搜索特定的东西。所以我想做一个call system("bash command")。这是我正在编写的函数:i.imgur.com/YnvLBSM.png
  • 你为什么要在vim写一个脚本?要么你正在做的是一个简单的一次性的,在这种情况下你会使用像 vim 这样的图形编辑器,或者它是不平凡的和/或经常重复的,然后你会使用像 awk 或这样的命令行编辑工具sed 甚至 ed。
  • 你想移动第8行,不管它包含什么,还是你想移动包含“index.php”的行,不管它在哪个行号上?

标签: linux bash shell awk sed


【解决方案1】:

假设你的文件名是test.txt,你可以试试这个: (请先备份您的文件)

grep "./index.php" test.txt > out && grep -v "./index.php" test.txt >> out && mv out test.txt 

【讨论】:

  • 不能指定行号吗?我必须在这里使用 grep 吗?
  • @Typewar 你也可以尝试使用sed
  • 由于某种原因它在字符串8:f4cd261a896fe4e7295146e7eb8ec39220e3aff1945e2e7ea57969199d5fab02, ./index.php前面设置了一个数字
  • 我不认为这很有效,因为您需要对同一个文件进行两次过滤,然后将结果连接起来,但它非常有创意。我喜欢这个解决方案
  • @Bri4n 它可能比使用 3 次 sed 调用和 2 个备份文件的 the currently accepted answer 更有效!
【解决方案2】:

我认为可以使用sed 来完成所需的操作: 该命令将用于获取文件中特定行的内容

sed -n "$LINE_NUMBER"p "$FILENAME"

该命令将用于删除指定行的文件内容

sed -i.bak -e "$LINE_NUMBER"'d' "$FILENAME"

最后,此命令将用于将字符串附加到文件的顶部

sed -i -e "1i${LINE_CONTENT}" "$FILENAME"

将这3个命令组合在一起,您可以执行问题中提到的操作(test.log是包含您的示例输入的文件)

FILENAME="test.log"
LINE_NUMBER=8
LINE_CONTENT=$(sed -n "$LINE_NUMBER"p "$FILENAME")
sed -i.bak -e "$LINE_NUMBER"'d' "$FILENAME"
sed -i -e "1i${LINE_CONTENT}" "$FILENAME"

【讨论】:

    【解决方案3】:

    使用ed,这也将进行就地编辑:

    printf '8m0\nwq\n' | ed -s ip.txt -
    

    或者,如果您不知道行号:

    printf '/index\.php/m0\nwq\n' | ed -s ip.txt -
    

    【讨论】:

      【解决方案4】:

      这可能对你有用(GNU sed):

      sed -E '1,8{H;8!d;p;x;s/^(.)(.*)\1.*/\2/}' file
      

      在保留空间中创建一系列行,从第一行到要插入到文件开头的行号(在上面的示例中为第 8 行)。

      当当前行是所需行时,打印它然后交换到保留空间,删除在范围开头引入的换行符和添加的最后一行(所需行)并打印剩余部分。

      所有其他行将正常打印。

      替代方案:

      sed -E '1{:a;N;8!ba;s/(.*)(\n)(.*)/\3\2\1/}' file
      

      另一个古怪的解决方案:

      sed '1,7{H;d};8{p;x;D}' file
      

      【讨论】:

        【解决方案5】:

        要完成这项工作,只需将输入文件读取一次,而无需将整个文件读入内存,并在每个 Unix 机器上的任何 shell 中使用任何 awk,您只需要以下任一:

        awk 'f{print; next} NR==8{print $0 buf; f=1} {buf=buf ORS $0}' file
        
        awk 'f{print; next} $2=="./index.php"{print $0 buf; f=1} {buf=buf ORS $0}' file
        

        如果要将第 8 行移到顶部:

        $ awk 'f{print; next} NR==8{print $0 buf; f=1} {buf=buf ORS $0}' file
        f412aabd74f4c99bd32c5e534132c565f52c2bd32fbf7f629eb5a4495ac46351, ./index.php
        6596628c9cbab49b80d6a07d0304377768f5114e7f8b21edffa820aab1c508be, ./favicon.ico
        150a04dd76f733e5ef05ece49de115d05f71efa8e73025e015dd4e0fb3217553, ./about.php
        28acfc4b0d378c22a2c0e4913cae3d15aef9b21938de81be92f74aef85b0cc0e, ./info.php
        67976bbbd1b62a00d454da3a9f95e72d97d0fd156d4c65a12707f2602cbea582, ./missing.php
        6ed318718f4cc617c82121db7cde54188eac6f89c355f0bfe9d198218de7fffc, ./browse.php
        abd277cc3453be980bb48cbffe9d1f7422ca1ef4bc0b7d035fda87cea4d55cbc, ./composer.phar
        73ac79eccac12120dc601cd6cce1282a1d8a920d440d3d1141d257db1ed4b0f0, ./search.php
        c2d49a4873088fbe635d8653494f7f1425b6ad9f55d63ee4de52170d8a8d01b8, ./content/style.css
        18e7d61367d80bc125b309ac002bb3946c5e7ba419ef59537afc939eff799dfd, ./content/logo.png
        d8da15f62d55641320f7e7c21d9be86db6d81f7667bbd35c738b4c917cad3ce9, ./robots.txt
        

        如果要将包含“index”的行移到顶部:

        $ awk 'f{print; next} $2=="./index.php"{print $0 buf; f=1} {buf=buf ORS $0}' file
        f412aabd74f4c99bd32c5e534132c565f52c2bd32fbf7f629eb5a4495ac46351, ./index.php
        6596628c9cbab49b80d6a07d0304377768f5114e7f8b21edffa820aab1c508be, ./favicon.ico
        150a04dd76f733e5ef05ece49de115d05f71efa8e73025e015dd4e0fb3217553, ./about.php
        28acfc4b0d378c22a2c0e4913cae3d15aef9b21938de81be92f74aef85b0cc0e, ./info.php
        67976bbbd1b62a00d454da3a9f95e72d97d0fd156d4c65a12707f2602cbea582, ./missing.php
        6ed318718f4cc617c82121db7cde54188eac6f89c355f0bfe9d198218de7fffc, ./browse.php
        abd277cc3453be980bb48cbffe9d1f7422ca1ef4bc0b7d035fda87cea4d55cbc, ./composer.phar
        73ac79eccac12120dc601cd6cce1282a1d8a920d440d3d1141d257db1ed4b0f0, ./search.php
        c2d49a4873088fbe635d8653494f7f1425b6ad9f55d63ee4de52170d8a8d01b8, ./content/style.css
        18e7d61367d80bc125b309ac002bb3946c5e7ba419ef59537afc939eff799dfd, ./content/logo.png
        d8da15f62d55641320f7e7c21d9be86db6d81f7667bbd35c738b4c917cad3ce9, ./robots.txt
        

        如果您有 GNU awk,则修改原始文件:

        awk -i inplace '...script...' file
        

        或使用任何 awk:

        awk '...script...' file > tmp && mv tmp file
        

        【讨论】:

        • 这是最好的答案!!简单而美丽。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-29
        • 1970-01-01
        • 1970-01-01
        • 2015-06-14
        • 2012-10-22
        相关资源
        最近更新 更多