使用“*”符号(不一定是那个,任何特殊字符都可以表示),我如何编辑以下文本:
*berry
straw
rasp
blue
boysen
*
blahblah
blahblah
blahblah
*berry
straw
blue
*
blah
*table
vege
pingpong
*
对此:
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
第一个匹配的星号后的每个字符都将放置在每一行上,直到找到第二个星号匹配。
关于我该如何解决这个问题有什么线索吗?(最好使用 sed 或 awk,但如果你能想到其他方法,请告诉我你的代码!)
我知道如何删除所有包含星号的行,只是我想不出字符放置部分
答案1
这段awk
代码就足够了:
awk -F'*' 'NF == 2 {label = $2; next} {$0 = $0 label} 1'
具体来说:
- 用作
*
字段分隔符。这样,我们可以简单地检查字段的数量(NF
)来确定是否已到达块的开头或结尾。 - 当有两个字段时,我们保存第二个字段
label
并继续下一行。 - 然后,我们将其附加
label
到当前行,然后打印。如果标签为空,则我们在块之外,没有任何效果。如果不是,我们将获得所需的输出。
答案2
在中sed
,你可以将“特殊”行复制到保留空间中,然后再删除它
sed -e '/^\*/{h;d;}'
然后将保留空间附加到每个后续的模式空间,替换生成的换行符和标记字符
-e '{G;s/\n\*//;}'
用你的数据进行测试,
$ sed -e '/^\*/{h;d;}' -e '{G;s/\n\*//;}' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
注意:当遇到第二个星号时,这不会停止;它的作用完全相同,但它会附加*
后面没有任何内容 - 直到它匹配下一个*sometext
。
答案3
这是一个 Perl 方法:
$ perl -lne '/^\*(.*)/ || print "$_$1"' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
解释
将-n
导致 Perl 读取输入文件的每一行,并将其保存在特殊变量中$_
,-l
将导致它 i)\n
从每行中删除尾随换行符 () 和 ii) 在每次调用时添加换行符print
。-e
是应用于每一行的脚本。
/^\*(.*)/
:匹配以星号开头的行,并将星号后的所有内容保存为$1
(这就是括号的作用)。|| print "$_$1"'
:||
是逻辑的OR
。因此,print
只有当前行不是以星号开头时才会执行。如果是这样,我们将打印当前行($_
)以及当前保存的内容$1
(星号后面的模式)。
像往常一样,有很多方法可以做到这一点。一种愚蠢且低效的方法,但可以突出 shell 的字符串处理能力,它是:
$ while read line; do
[[ $line =~ ^\* ]] && pat="${line#\*}" || printf "%s%s\n" "$line" "$pat";
done < file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
解释
while read line; do ... ; done < file
:这是一个经典的while
循环,它将读取输入文件的每一行file
并将其保存为$line
。[[ $line =~ ^\* ]] && pat="${line#\*}"
:如果行以 开头*
,则删除其后的所有内容(这就是 的作用${line#\*}
,有关更多详细信息,请参阅这里) 并将其保存为$pat
。 *|| printf "%s%s\n" "$line" "$pat";
:如果前一个命令失败(因此,该行不以星号开头),则打印该行和 的当前值$pat
。
答案4
来晚了。这是另一种python
方法:
#!/usr/bin/env python2
with open('/path/to/file.txt') as f:
for lines in f.read().split('*'):
entries = lines.rstrip().split('\n')
for i in range(1, len(entries)):
print entries[i] + entries[0]