如何在linux中获取文件的最后一行前2个字符

时间:2018-03-12 05:34:23

标签: linux bash shell awk sed

我的文件包含以下格式,由其他系统生成

 12;453453;TBS;OPPS;
 12;453454;TGS;OPPS;
 12;453455;TGS;OPPS;
 12;453456;TGS;OPPS;
 20;787899;THS;CLST;
 33;786789;

我必须检查最后一行包含33,然后必须继续将文件/文件复制到其他位置。否则丢弃该文件。

目前我正在做如下

tail -1 abc.txt >> c.txt
awk '{print substr($0,0,2)}' c.txt

然后如果将o / p保存到另一个变量并复制。 任何人都可以建议任何其他简单方法。

谢谢!

R /

3 个答案:

答案 0 :(得分:4)

想象一下,您有以下输入文件:

$ cat file
a
b
c
d
e
agc

然后,您可以运行以下命令(grepawksedcut)以获取最后一行的前2个字符:

<强> AWK

$ awk 'END{print substr($0,0,2)}' file
ag

<强> SED

$ sed -n '$s/^\(..\).*/\1/p' file                             
ag

<强> GREP

$ tail -1 file | grep -oE '^..' 
ag

<强> CUT

$ tail -1 file | cut -c '1-2' 
ag

BASH SUBSTRING

line=$(tail -1 file); echo ${line:0:2}

所有这些命令都能满足您的需求,awk命令只会对文件的最后一行执行操作,因此您不再需要tail,所述命令将会提取文件的最后一行并将其存储在其模式缓冲区中,然后将所有不是前2个字符的内容替换为空,然后打印模式缓冲区(最后一行的2个字符),另一个解决方案就是{{ 1}}文件的最后一行,并使用tail提取前两个字符,通过管道这2个命令,您也可以一步完成,而不使用中间变量,文件。

现在,如果你想将所有内容放在一个脚本中,那就变成了:

grep

执行:

$ more file check_2chars.sh 
::::::::::::::
file
::::::::::::::
a
b
c
d
e
33abc
::::::::::::::
check_2chars.sh
::::::::::::::
#!/bin/bash
s1=$(tail -1 file | cut -c 1-2) #you can use other commands from this post
s2=33

if [ "$s1" == "$s2" ] 
then
   echo "match" #implement the copy/discard logic
fi

我会让你实现复制/丢弃逻辑

<强> PROOF:

enter image description here

答案 1 :(得分:2)

根据内容复制或删除文件的任务,不需要shell变量。

使用sed F 名称命令和xargs,整个任务只需一行即可完成:

find | xargs -l sed -n '${/^33/!F}' | xargs -r rm ; cp * dest/dir/

或者最好是 GNU sed

sed -sn '${/^33/!F}' * | xargs -r rm ; cp * dest/dir/

或者,如果所有文件名都不包含空格:

rm -r $(sed -sn '${/^33/!F}' *) ; cp * dest/dir/

假设要测试当前目录中的所有文件。

  1. sed查看每个文件的最后一行($),然后运行花括号中的内容。
  2. 如果这些最后一行中的任何一行不以 33 /^33/!)开头,则sed仅输出那些不需要的文件名(F)。
  3. 假设不需要的文件名为 foo baz - 这些文件通过管道传送到运行xargs的{​​{1}}。
  4. 此时,剩下的唯一文件应该复制到 dest / dir / rm foo baz
  5. 效率很高,cp * dest/dir/cp只需运行一次。

    如果必须使用shell变量,则还有两种方法:

    使用rmtail,将最后一行的前两个字符存储到bash

    $n

    这是一个更便携的 POSIX shell版本:

    n="$(tail -1 abc.txt)" n="${n:0:2}"
    

答案 2 :(得分:0)

您可以使用sed显式测试以33(/^33.*/)开头的最后一行($):

echo " 12;453453;TBS;OPPS;
12;453454;TGS;OPPS;
12;453455;TGS;OPPS;
12;453456;TGS;OPPS;
20;787899;THS;CLST;
33;786789;" | sed -n "$ {/^33.*/p}"
33;786789;

如果将结果存储在变量中,则可以测试它是否为空:

lastline33=$(echo " 12;453453;TBS;OPPS;
12;453454;TGS;OPPS;
12;453455;TGS;OPPS;
12;453456;TGS;OPPS;
20;787899;THS;CLST;
33;786789;" | sed -n "$ {/^33.*/p}")

echo $(test -n "$lastline33" && echo not null || echo null) 
not null

可能你喜欢正则表达式来包含分号,因为它会匹配330,331,... 339,33401345等等,但也许可以从上下文中排除 - 对我来说这似乎是一个好主意:

lastline33=$(sed -n "$ {/^33;.*/p}" abc.txt)