awk 方法:

awk 方法:

我有一个保存了数据的文件。现在我想将结果打印到一个新文件中。

例如,让我们来看这个例子randomlog.log

Link encap:Ethernet HWaddr 08:00:00:00:00:67
inet addr:10.10.10.10 Bcast:10.10.10.10 Mask:255.255.255.0
inet6 addr: fe80::casf:sdfg:23ra:dg12/64 Scope:Link

我怎样才能只取第一行第 12 到第 20 个字符的数据,然后取第三行第 4 到第 8 个字符的数据?输出将如下所示:

Ethernet
t6 ad

这可能吗?我想设置线并从位置到该位置。

答案1

这里有一种sed方法:

$ sed -nE '1s/.{11}(.{8}).*/\1/p; 3s/.{3}(.{4}).*/\1/p' file  
Ethernet
t6 a

解释

抑制-n正常输出(正常是打印每个输入行),以便只在收到通知时才打印。-E启用扩展正则表达式。

sed脚本有两个命令,均使用替换运算符 ( s/original/replacement/)。1s/.{11}(.{8}).*/\1/p只会在第一行运行(这就是 的作用1s),并将匹配该行的前 11 个字符(.{11}),然后它捕获接下来的 8 个字符((.{8}),括号是“捕获组”),然后是其他所有字符,直到行尾(.*)。所有这些都将替换为捕获组中的内容(\1;如果有第二个捕获组,则为 等等\2)。最后,p末尾的 ( s/foo/bar/p) 导致在替换后打印该行。这导致仅输出目标 8 个字符。

第二条命令的总体思路是相同的,只是它只会在第三行(3s)运行,并且会保留从第 4 个字符开始的 4 个字符。


你也可以用以下方法做同样的事情perl

$ perl -ne 'if($.==1){s/.{11}(.{8}).*/\1/}
            elsif($.==3){s/.{3}(.{4}).*/\1/}
            else{next}; print; ' file 
Ethernet
t6 a

解释

意思是-ne“逐行读取输入文件并将给出的脚本应用于-e每一行。脚本的基本思想与以前相同。变量$.保存当前行号,因此我们检查行号是否为13,如果是,则运行替换,否则跳过。因此,print只会对这两行运行,因为所有其他行都将被跳过。


当然,这是 Perl,所以蒂姆托

$ perl -F"" -lane '$. == 1 && print @F[11..19]; $.==3 && print @F[3..6]' file 
Ethernet 
t6 a

解释

这里, 的-a意思是“根据 给出的字符分割每一行输入-F,并保存为数组@F。由于给定的字符为空,这会将输入行的每个字符保存为 中的一个元素@F。然后,我们为第一行打印元素 11-19(数组从 开始计数0),为第三行打印元素 3-7。

答案2

awk 方法:

$ awk 'NR==1{print substr($0,12,8)};NR==3{print substr($0,4,4)}' input.txt  
Ethernet
t6 a

用于NR确定行号(在 awk 术语中为记录),并据此打印行的子字符串。substr()函数格式为

substr(string,starting position,how much offset) 

Python

$ python -c 'import sys                                                                                                                                                
> for index,line in enumerate(sys.stdin,1):                                                                                                                            
>     if index == 1:
>          print line[11:19]
>     if index == 3:
>          print line[3:7]' < input.txt
Ethernet
t6 a

这使用<shell 运算符将输入流从输入文件重定向到 python 进程。请注意,python 中的字符串是从 0 开始的,因此您需要将所需的字符数全部移动 1。

便携外壳方式

这在kshdash、中有效bash。仅依赖于 shell 实用程序,无需任何外部工具。

#!/bin/sh

rsubstr(){
    i=0;
    while [ $i -lt  $2 ];
    do
        rmcount="${rmcount}?"
        i=$(($i+1))
    done;
    echo "${1#$rmcount}"
}

lsubstr(){
    printf "%.${2}s\n" "$1"
}

line_handler(){
    case $2 in
        1) lsubstr "$(rsubstr "$1" 11)" 8 ;;
        3) lsubstr "$(rsubstr "$1" 3)" 5 ;;
    esac
}

readlines(){
    line_count=1
    while IFS= read -r line;
    do
        line_handler "$line" "$line_count"
        line_count=$(($line_count+1))
    done < $1
}

readlines "$1"

它的工作原理如下:

$ ./get_line_substrings.sh input.txt                                                                                                                                   
Ethernet
t6 ad

相关内容