如何使用 sed/awk 每两行切换/旋转?

发布于 2024-11-26 08:47:39 字数 719 浏览 0 评论 0原文

我一直在手工做这件事,但我不能再这样做了——我有数千行,我认为这是 sed 或 awk 的工作。

本质上,我们有一个像这样的文件:

A sentence X
A matching sentence Y
A sentence Z
A matching sentence N

整个文件都延续这种模式。我想翻转每个句子和匹配的句子,这样整个文件就会像这样:

A matching sentence Y
A sentence X
A matching sentence N
A sentence Z

有什么提示吗?

编辑:扩展最初的问题

Dimitre Radoulov 为最初的问题提供了一个很好的答案。这是主要问题的扩展 - 一些更多细节:

假设我们有一个组织好的文件(由于 Dimitre 给出的 sed 行,该文件是组织好的)。但是,现在我想按字母顺序组织文件,但仅使用第二行的语言(英语)。

watashi 
me
annyonghaseyo
hello
dobroye utro!
Good morning!

我想通过英语句子(每第二句)按字母顺序组织。给定上述输入,输出应该是:

dobroye utro!
Good morning!
annyonghaseyo
hello
watashi
me 

I have been doing this by hand and I just can't do it anymore-- I have thousands of lines and I think this is a job for sed or awk.

Essentially, we have a file like this:

A sentence X
A matching sentence Y
A sentence Z
A matching sentence N

This pattern continues for the entire file. I want to flip every sentence and matching sentence so the entire file will end up like:

A matching sentence Y
A sentence X
A matching sentence N
A sentence Z

Any tips?

edit: extending the initial problem

Dimitre Radoulov provided a great answer for the initial problem. This is an extension of the main problem-- some more details:

Let's say we have an organized file (due to the sed line Dimitre gave, the file is organized). However, now I want to organize the file alphabetically but only using the language (English) of the second line.

watashi 
me
annyonghaseyo
hello
dobroye utro!
Good morning!

I would like to organize alphabetically via the English sentences (every 2nd sentence). Given the above input, this should be the output:

dobroye utro!
Good morning!
annyonghaseyo
hello
watashi
me 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情定在深秋 2024-12-03 08:47:39

对于问题的第一部分,这里有一种在 sed 中相互交换每一行而不使用正则表达式的方法:

sed -n 'h;n;p;g;p'

-n 命令行抑制自动打印。命令 h put 将当前行从模式空间复制到保留空间,n 将下一行读入模式空间,p 打印它; g 将第一行从保留空间复制回模式空间,将第一行带回模式空间,然后 p 打印它。

For the first part of the question, here is a one way to swap every other line with each other in sed without using regular expressions:

sed -n 'h;n;p;g;p'

The -n command line suppresses the automatic printing. Command h puts copies the current line from the pattern space to the hold space, n reads in the next line to the pattern space and p prints it; g copies the first line from the hold space back to the pattern space, bringing the first line back into the pattern space, and p prints it.

世态炎凉 2024-12-03 08:47:39
sed 'N; 
s/\(.*\)\n\(.*\)/\2\
\1/' infile

N - 将下一行输入附加到模式空间
\(.*\)\n\(.*\) - 保存模式空间的匹配部分
换行符之前和之后的一个。
<代码>\2\\
\1 - 交换两行(\1 是第一个保存的部分,
\2 第二个)。使用转义文字换行符实现可移植性

对于某些 sed 实现,您可以使用转义序列
\n:改为 \2\n\1

sed 'N; 
s/\(.*\)\n\(.*\)/\2\
\1/' infile

N - append the next line of input into the pattern space
\(.*\)\n\(.*\) - save the matching parts of the pattern space
the one before and the one after the newline.
\2\\
\1
- exchange the two lines (\1 is the first saved part,
\2 the second). Use escaped literal newline for portability

With some sed implementations you could use the escape sequence
\n: \2\n\1 instead.

飘过的浮云 2024-12-03 08:47:39

第一个问题:

awk '{x = $0; getline; print; print x}' filename

下一个问题: 按第二行排序

paste - - < filename | sort -f -t 

,输出:

dobroye utro!
Good morning!
annyonghaseyo
hello
watashi
me
\t' -k 2 | tr '\t' '\n'

,输出:

First question:

awk '{x = $0; getline; print; print x}' filename

next question: sort by 2nd line

paste - - < filename | sort -f -t 

which outputs:

dobroye utro!
Good morning!
annyonghaseyo
hello
watashi
me
\t' -k 2 | tr '\t' '\n'

which outputs:

温暖的光 2024-12-03 08:47:39

假设像这样的输入文件:

A sentence X
Z matching sentence Y
A sentence Z
B matching sentence N
A sentence Z
M matching sentence N

您可以使用 Perl 进行交换和排序:

perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort keys %_; 
   }' infile

我得到的输出是:

% perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort keys %_;
   }' infile
B matching sentence N
A sentence Z
M matching sentence N
A sentence Z
Z matching sentence Y
A sentence X

如果您想按第一行排序(在交换之前):

perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort {
      $_{ $a } cmp $_{ $b }
      } keys %_; 
   }' infile

那么,如果原始文件如下所示:

% cat infile1
me
watashi 
hello
annyonghaseyo
Good morning!
dobroye utro!

输出应如下所示:

% perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort {
  $_{ $a } cmp $_{ $b }
  } keys %_;
   }' infile1
dobroye utro!
Good morning!
annyonghaseyo
hello
watashi 
me

此版本应正确处理重复记录:

perl -lne'
 $_{ $_, $. } = $v unless $. % 2;
 $v = $_;
 END {
    print substr( $_, 0, length() - 1) , $/, $_{ $_ }
    for sort {
      $_{ $a } cmp $_{ $b }
      } keys %_; 
   }' infile

另一个版本受 Glenn 发布的解决方案启发(包括记录交换并假设文本文件中不存在模式 _ZZ_):

sed 'N; 
  s/\(.*\)\n\(.*\)/\1_ZZ_\2/' infile | 
    sort |
      sed 's/\(.*\)_ZZ_\(.*\)/\2\
\1/'

Assuming an input file like this:

A sentence X
Z matching sentence Y
A sentence Z
B matching sentence N
A sentence Z
M matching sentence N

You could do both exchange and sort with Perl:

perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort keys %_; 
   }' infile

The output I get is:

% perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort keys %_;
   }' infile
B matching sentence N
A sentence Z
M matching sentence N
A sentence Z
Z matching sentence Y
A sentence X

If you want to order by the first line (before the exchange):

perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort {
      $_{ $a } cmp $_{ $b }
      } keys %_; 
   }' infile

So, if the original file looks like this:

% cat infile1
me
watashi 
hello
annyonghaseyo
Good morning!
dobroye utro!

The output should look like this:

% perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort {
  $_{ $a } cmp $_{ $b }
  } keys %_;
   }' infile1
dobroye utro!
Good morning!
annyonghaseyo
hello
watashi 
me

This version should handle duplicate records correctly:

perl -lne'
 $_{ $_, $. } = $v unless $. % 2;
 $v = $_;
 END {
    print substr( $_, 0, length() - 1) , $/, $_{ $_ }
    for sort {
      $_{ $a } cmp $_{ $b }
      } keys %_; 
   }' infile

And another version, inspired by the solution posted by Glenn (record exchange included and assuming the pattern _ZZ_ is not present in the text file):

sed 'N; 
  s/\(.*\)\n\(.*\)/\1_ZZ_\2/' infile | 
    sort |
      sed 's/\(.*\)_ZZ_\(.*\)/\2\
\1/'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文