获取第N个域及其之后的内容?

sh/bash/dash/ksh/zsh等Shell脚本
头像
lilydjwg
论坛版主
帖子: 4249
注册时间: 2009-04-11 23:46
系统: Arch Linux
联系:

获取第N个域及其之后的内容?

#1

帖子 lilydjwg » 2012-08-23 13:22

代码: 全选

  AAA BBB     CCC         DDD dd DdDd
如何获取到DDD dd DdDd呢?
类似于 Python 的 line.split(None, N)[-1] 这样子。
头像
ljj_jjl2008
论坛版主
帖子: 14255
注册时间: 2007-09-16 8:29

Re: 获取第N个域及其之后的内容?

#2

帖子 ljj_jjl2008 » 2012-08-23 13:28

这是我写过的一个函数,获得字符串第n段内容的。
不能直接解决你的问题,可以作为参考。

代码: 全选

int get_str2(char * jg,char *fullstr,int n_id)
{
    char f_buffer[4096],ch2[4096];
    int i,n,o,p,yh;
    sprintf(f_buffer,"%s",fullstr);
    p=0;
    i=0;
    while (1)
    {
        o=0;
        yh=0;
        for (n=0;n<4096;n++)
            ch2[n]='\0';
        for (n=p;n<4096;n++)
        {
            if ((yh==0) and (f_buffer[n]==' '))
                continue;
    //                                printf("%c\n",f_buffer[n]);
            if ((yh==1) and (f_buffer[n]=='\"') and (f_buffer[n-1]!='\\'))
                break;
            if (((f_buffer[n]=='\"') and (n==p)) or ((f_buffer[n]=='\"') and (n>p) and (f_buffer[n-1]!='\\')))
            {
                yh=1;
                continue;
            }
            if ((yh==2) and (f_buffer[n]==' '))
                break;
            if ((yh==0) and (f_buffer[n]!=' '))
                yh=2;
            if (yh>0)
            {
                ch2[o]=f_buffer[n];
                o=o+1;
            }
        }
        if (yh==1)
            p=n+1;
        else
            p=n;
        i=i+1;
        if (i==n_id)
        {
            sprintf(jg,"%s",ch2);
            return 0;
        }
    }
    return -1;
}
头像
Methuselar
帖子: 122
注册时间: 2009-06-04 12:06
联系:

Re: 获取第N个域及其之后的内容?

#3

帖子 Methuselar » 2012-08-23 13:43

如果你知道位置:

代码: 全选

cut -d' ' -f4-
如果你知道需要去掉的字符:

代码: 全选

sed 's/AAA\ \+BBB\ \+CCC\ \+//'
Mea Culpa!
头像
lilydjwg
论坛版主
帖子: 4249
注册时间: 2009-04-11 23:46
系统: Arch Linux
联系:

Re: 获取第N个域及其之后的内容?

#4

帖子 lilydjwg » 2012-08-23 14:26

Methuselar, 我知道位置,但是域是以 \s+ 分隔的,并且第一个域要求不为空,所以 cut 不行。
ljj_jjl2008, 写得比 Python 还长……
头像
Methuselar
帖子: 122
注册时间: 2009-06-04 12:06
联系:

Re: 获取第N个域及其之后的内容?

#5

帖子 Methuselar » 2012-08-23 15:22

lilydjwg 写了:Methuselar, 我知道位置,但是域是以 \s+ 分隔的,并且第一个域要求不为空,所以 cut 不行。
ljj_jjl2008, 写得比 Python 还长……
\s+分割,cut可以。第一域要求不空,是什么意思,是指^\s+的行全部不操作,还是说^\s+的行你就取从N-1域开始??
Mea Culpa!
头像
ljj_jjl2008
论坛版主
帖子: 14255
注册时间: 2007-09-16 8:29

Re: 获取第N个域及其之后的内容?

#6

帖子 ljj_jjl2008 » 2012-08-23 15:23

lilydjwg 写了:Methuselar, 我知道位置,但是域是以 \s+ 分隔的,并且第一个域要求不为空,所以 cut 不行。
ljj_jjl2008, 写得比 Python 还长……
哎,我写的程序,就是用来接受BS的。
头像
Methuselar
帖子: 122
注册时间: 2009-06-04 12:06
联系:

Re: 获取第N个域及其之后的内容?

#7

帖子 Methuselar » 2012-08-23 15:55

这样往死里作总可以了吧...

代码: 全选

awk -vPOS=你想要的位置 '{printf $POS;for (i=POS+1;i<=NF;i++) printf " "$i;printf "\n"}'
但如果你需要保留空格的个数, 那就不是这样的情况了. awk可以动态生成正则:

代码: 全选

awk -vPOS=你想要的位置 '{ ma="^ *"; for (i=1;i<=POS;i++){ ma=ma$i" *";}; sub(ma, "", $0); print $0;}'
上次由 Methuselar 在 2012-08-23 17:49,总共编辑 1 次。
Mea Culpa!
头像
lilydjwg
论坛版主
帖子: 4249
注册时间: 2009-04-11 23:46
系统: Arch Linux
联系:

Re: 获取第N个域及其之后的内容?

#8

帖子 lilydjwg » 2012-08-23 16:43

Methuselar 写了:这样往死里作总可以了吧...

代码: 全选

awk -vPOS=$你想要的位置 '{printf $POS;for (i=POS+1;i<=NF;i++) printf " "$i;printf "\n"}'
但如果你需要保留空格的个数, 那就不是这样的情况了.
对,空格个数要保留。
Methuselar 写了:
lilydjwg 写了:Methuselar, 我知道位置,但是域是以 \s+ 分隔的,并且第一个域要求不为空,所以 cut 不行。
ljj_jjl2008, 写得比 Python 还长……
\s+分割,cut可以。第一域要求不空,是什么意思,是指^\s+的行全部不操作,还是说^\s+的行你就取从N-1域开始??
cut 怎么做?就是要求去掉 ^\s+ 再分割那样,不要把数据右对齐造成的空格前被当成空的域。
头像
lilydjwg
论坛版主
帖子: 4249
注册时间: 2009-04-11 23:46
系统: Arch Linux
联系:

Re: 获取第N个域及其之后的内容?

#9

帖子 lilydjwg » 2012-08-23 16:44

我还是自己写个程序吧哎。
头像
ljj_jjl2008
论坛版主
帖子: 14255
注册时间: 2007-09-16 8:29

Re: 获取第N个域及其之后的内容?

#10

帖子 ljj_jjl2008 » 2012-08-23 16:45

我其实很讨厌这种讨论:有这种讨论时间,够写200个程序的了。
头像
lilydjwg
论坛版主
帖子: 4249
注册时间: 2009-04-11 23:46
系统: Arch Linux
联系:

Re: 获取第N个域及其之后的内容?

#11

帖子 lilydjwg » 2012-08-23 16:55

ljj_jjl2008 写了:我其实很讨厌这种讨论:有这种讨论时间,够写200个程序的了。
问题是,自己写的程序携带不便啊。我工作时经常得从自己笔记本上拷个把脚本过去……
头像
ljj_jjl2008
论坛版主
帖子: 14255
注册时间: 2007-09-16 8:29

Re: 获取第N个域及其之后的内容?

#12

帖子 ljj_jjl2008 » 2012-08-23 16:59

lilydjwg 写了:
ljj_jjl2008 写了:我其实很讨厌这种讨论:有这种讨论时间,够写200个程序的了。
问题是,自己写的程序携带不便啊。我工作时经常得从自己笔记本上拷个把脚本过去……
作成deb包,把依赖的包也顺便下载deb来放在一起。
头像
Methuselar
帖子: 122
注册时间: 2009-06-04 12:06
联系:

Re: 获取第N个域及其之后的内容?

#13

帖子 Methuselar » 2012-08-23 17:36

lilydjwg 写了: cut 怎么做?就是要求去掉 ^\s+ 再分割那样,不要把数据右对齐造成的空格前被当成空的域。
那光cut不行, cut是极少数记录分段位置的工具,也就拥有简单的输出第N列以后的所有数据的能力。
awk 没记录,所以不可能简单的做到 cut -d' ' -f3- 那么简单. 我第二个awk里sub的匹配和替换开销极大,当然数据不大(不上G)是无所谓的。
数据大的话, 就用C/Java那样的做法了。

但也正因为那样,cut只能从具体数据获取列数信息

话说, 讨论讨论不也挺好...
Mea Culpa!
头像
lilydjwg
论坛版主
帖子: 4249
注册时间: 2009-04-11 23:46
系统: Arch Linux
联系:

Re: 获取第N个域及其之后的内容?

#14

帖子 lilydjwg » 2012-08-23 17:47

Methuselar 写了:
lilydjwg 写了: cut 怎么做?就是要求去掉 ^\s+ 再分割那样,不要把数据右对齐造成的空格前被当成空的域。
那光cut不行, cut是极少数记录分段位置的工具,也就拥有简单的输出第N列以后的所有数据的能力。
awk 没记录,所以不可能简单的做到 cut -d' ' -f3- 那么简单. 我第二个awk里sub的匹配和替换开销极大,当然数据不大(不上G)是无所谓的。
数据大的话, 就用C/Java那样的做法了。

但也正因为那样,cut只能从具体数据获取列数信息

话说, 讨论讨论不也挺好...
第一个问题我问的是怎么以 \s+ 作为分隔符。去 ^\s+ 我 sed 一下就行了。
我今天用的那个方法调用 Python,写了十来行呢……哦,它同时把 uniq -c 的活也干了。
tusooa
帖子: 6548
注册时间: 2008-10-31 22:12
系统: 践兔
联系:

Re: 获取第N个域及其之后的内容?

#15

帖子 tusooa » 2012-08-27 14:04

lilydjwg 写了:

代码: 全选

  AAA BBB     CCC         DDD dd DdDd
如何获取到DDD dd DdDd呢?
类似于 Python 的 line.split(None, N)[-1] 这样子。

代码: 全选

● echo '  AAA BBB     CCC         DDD dd DdDd'|awk -F' +' '{for (i=5;i<=NF;i++){printf $i " ";}}'
DDD dd DdDd %

代码: 全选

] ls -ld //
回复