我有一个像这里这样的文件 file.txt
bbb-ccc-cccc#
aasdf asdas asdasa fgdg
asdfa asfdas adfaq asfa
afdaf fafa fafd afafa
bbb-ccc-cccc#
我想获取以 结尾的单词#
,并将其作为第一个单词添加到每一行。
sed 's/bbb-ccc-cccc#/^/' < file.txt > newfile.txt
我提前不知道 # 符号之前的单词,所以我的观点是找到以 结尾的单词#
并将其放在每行的开头。对于这个 file.txt 我需要像这样:
bbb-ccc-cccc#
bbb-ccc-cccc# aasdf asdas asdasa fgdg
bbb-ccc-cccc# asdfa asfdas adfaq asfa
bbb-ccc-cccc# afdaf fafa fafd afafa
bbb-ccc-cccc#
答案1
和perl
:
perl -lpe 'if (/\H+#/) {$word = $&} else {$_ = $word . $_}'
也就是说,如果我们在一行中找到一系列非空白字符 ( \H+
) 后跟 a ,我们将使用该序列(正则表达式匹配的内容)作为要插入到下一行开头的单词。#
$&
awk
与:相同
awk '
match($0, /[^[:blank:]]+#/) {
word = substr($0, RSTART, RLENGTH)
print
next
}
{print word $0}'
与sed
(使用保留空间来存储单词):
sed '
/[^[:blank:]]\{1,\}#/ {
h; # save the line in the hold space
s//\
&\
/; # put newlines on each side of the matched word
s/.*\n\(.*\)\n/\1/; # remove every thing but the word
x; # swap hold and pattern space so that now the hold
# space contains the word. And branch off:
b
}
# for the other lines:
G; # append the hold space to the pattern space
s/\(.*\)\n\(.*\)/\2\1/; # move the word to the beginning'
如果您只想匹配word#
行尾的 s,请在上面的所有 3 个命令中替换#
为。#$
答案2
使用awk
:
$ awk '/^[^ ]*#$/ { prefix = $0; print; next } { print prefix, $0 }' file
bbb-ccc-cccc#
bbb-ccc-cccc# aasdf asdas asdasa fgdg
bbb-ccc-cccc# asdfa asfdas adfaq asfa
bbb-ccc-cccc# afdaf fafa fafd afafa
bbb-ccc-cccc#
这将打印带有前缀的每一行。前缀取自与模式匹配的任何行^[^␣]*#$
,即完全由非空格字符组成并以 结尾的行#
。打印这些行时没有附加前缀,并且处理将继续处理下一个输入行。
答案3
这是我的解决方案gnu sed
:
sed '/\(.*\)#/{h;:y;n;/\(.*\)#/b;G;s/\(.*\)\n\(.*\)/\2\1/;by}' test.txt
快速解释:
- h 将当前缓冲区复制到“保留空间”
- G 将“保留空间”附加到当前缓冲区(添加需要删除的进位返回)
- :xxx 是标签
- bxxx 是 goto。 “b”单独到达脚本的末尾
- n 打印当前缓冲区并读取下一行
这是我的 bash 解决方案:
while IFS='' read -r x;do if [[ "$x" = *# ]] ; then if [ "$p" = "$x" ]; then p=''; else p="$x"; x=''; fi ; fi; printf '%s%s\n' "$p" "$x";done < test.txt
答案4
在bash中:
#!/bin/bash
# grab one of the lines ending in #
prefix=$(egrep '#$' file | head -1)
cat file | while read line
do
# if the line ends in a #, just print it
if [[ $line =~ \#$ ]]
then
echo $line
else
# print the line prefixed with the $prefix
printf -- "%s %s\n" "$prefix" "$line"
fi
done
[[ $line =~ \#$ ]]
是一个正则表达式 if 语句,与egrep
.如果您的 shell 不喜欢它,您可以将其替换为if egrep -q '#$' <<< line; then
.