我有一个单行大字符串,其中包含'〜|〜'作为分隔符。 10个字段组成一行,第10个字段长9个字符。我想在每一行之后插入一个新行,这意味着在(9,18,27 ..)出现'〜|〜'
之后插入一个updated_at
10个字符
是否有快速单行sed / awk选项可用而不通过字符串循环?
我用过
$user->touch()
但它将用新行替换每第10次出现。我想保留分隔符,但在字段10中的9个字符后添加一个新行
\n
以下是我想要的内容
sed -e's/\(\([^~|~]*~|~\)\{9\}[^~|~]*\)~|~/\1\n/g'
答案 0 :(得分:1)
让我们试试awk:
awk 'BEGIN{FS="[~|~]+"; OFS="~|~"}
{for(i=10; i<NF; i+=9){
str=$i
$i=substr(str, 1, 9)"\n"substr(str, 10, length(str))
}
print $0}' t.txt
输入:
one~|~two~|~three~|~four~|~five~|~six~|~seven~|~eight~|~nine~|~ten1234562one~|~2two~|~2three~|~2four~|~2five~|~2six~|~2seven~|~2eight~|~2nine~|~2ten1234563one~|~3two~|~3three~|~3four~|~3five~|~3six~|~3seven~|~3eight~|~3nine~|~3ten123456
输出:
one~|~two~|~three~|~four~|~five~|~six~|~seven~|~eight~|~nine~|~ten123456
2one~|~2two~|~2three~|~2four~|~2five~|~2six~|~2seven~|~2eight~|~2nine~|~2ten12345
63one~|~3two~|~3three~|~3four~|~3five~|~3six~|~3seven~|~3eight~|~3nine~|~3ten123456
我认为您的评论中有一些错误:如果您的输入包含ten1234562one
和2ten1234563one
,则必须在第一种情况下2
之后和{{{}之后插入换行符1}}在第二种情况下(因为这是第十个字符)。但是你的预期输出与此不同。
答案 1 :(得分:0)
你的sed
脚本并不太远。这似乎可以完成你想要的工作:
sed -e '/^$/d' \
-e 's/\([^~|]*~|~\)\{9\}.\{9\}/&\' \
-e '/' \
-e 'P;D' \
data
对于您的输入文件(我称之为data
),我得到:
one~|~two~|~three~|~four~|~five~|~six~|~seven~|~eight~|~nine~|~ten123456
2one~|~2two~|~2three~|~2four~|~2five~|~2six~|~2seven~|~2eight~|~2nine~|~2ten12345
63one~|~3two~|~3three~|~3four~|~3five~|~3six~|~3seven~|~3eight~|~3nine~|~3ten12345
6
我担心脚本需要一点解释。它使用了一些模糊的shell和一些模糊的sed
行为。晦涩的shell行为是在单引号字符串中,反斜杠没有特殊含义,因此第二个-e
中第二个单引号之前的反斜杠在sed
处显示为结尾处的反斜杠论点。晦涩的sed
行为是它将每个-e
选项的参数视为一条线。因此,在第三个/
之后的尾随反斜杠加-e
被视为有反斜杠,换行符,斜杠序列,这就是BSD sed
(和POSIX {{1} })要求您添加换行符。 GNU sed
将替换中的sed
视为换行符,但POSIX(和BSD)说:
转义序列“
\n
”应匹配模式空间中嵌入的\n
。
在<newline>
替换的替换部分中,\n
没有说明<newline>
被视为s///
。因此,前两个-e
选项组合在匹配后添加换行符。匹配的是什么?好吧,这是一系列'零或多个非波形,非管道字符后跟~|~
',重复9次,然后是9'任何字符'。这是你想要的近似值。如果你有~|~tilde~pipe|bother~|~
这样的字段,那么正则表达式会失败,因为'tilde'和'pipe'之间的~
以及'pipe'之间的|
和'打扰' ”。修复它来处理所有可能的序列是非常重要的,并且样本数据无法保证。
脚本的其余部分是直截了当的:-e '/^$/d'
删除一个空行,如果数据的长度恰好合适则重要,在-e 'P;D'
P
打印模式空间的初始段直到第一个换行符(我们刚刚添加的换行符); D
删除模式空间的初始段直到第一个换行符并重新开始。
我不相信这是值得的复杂性。如果脚本位于文件script.sed
:
/^$/d
s/\([^~|]*~|~\)\{9\}.\{9\}/&\
/
P
D
,命令行是:
$ sed -f script.sed data
one~|~two~|~three~|~four~|~five~|~six~|~seven~|~eight~|~nine~|~ten123456
2one~|~2two~|~2three~|~2four~|~2five~|~2six~|~2seven~|~2eight~|~2nine~|~2ten12345
63one~|~3two~|~3three~|~3four~|~3five~|~3six~|~3seven~|~3eight~|~3nine~|~3ten12345
6
$
毋庸置疑,它会产生相同的输出。如果没有/^$/d
,脚本只能在输入结尾处使用奇数6
。在第三条记录之后恰好有9个字符,然后它会在无限循环中翻转。
如果您使用扩展正则表达式,则可以处理中间包含~
或|
(或实际上~|
)的奇数球。
script2.sed
:
/^$/d
s/(([^~|]{1,}|~[^|]|~\|[^~])*~\|~){9}.{9}/&\
/
P
D
data2
:
one~|~two~|~three~|~four~|~five~|~six~|~seven~|~eight~|~nine~|~ten1234562one~|~2two~|~2three~|~2four~|~2five~|~2six~|~2seven~|~2eight~|~2nine~|~2ten1234563one~|~3two~|~3three~|~3four~|~3five~|~3six~|~3seven~|~3eight~|~3nine~|~3ten12345666=beast~tilde|pipe~|twiddle~|~4-two~|~4-three~|~4-four~|~4-five~|~4-six~|~4-seven~|~4-eighty-eight~|~4-999~|~987654321
sed -E -f script.sed data2
的输出:
one~|~two~|~three~|~four~|~five~|~six~|~seven~|~eight~|~nine~|~ten123456
2one~|~2two~|~2three~|~2four~|~2five~|~2six~|~2seven~|~2eight~|~2nine~|~2ten12345
63one~|~3two~|~3three~|~3four~|~3five~|~3six~|~3seven~|~3eight~|~3nine~|~3ten12345
666=beast~tilde|pipe~|twiddle~|~4-two~|~4-three~|~4-four~|~4-five~|~4-six~|~4-seven~|~4-eighty-eight~|~4-999~|~987654321
仍然无法处理像tilde~~|~
这样的字段。使用-E
对于BSD(Mac OS X)sed
是正确的。它可以扩展正则表达式。 GNU sed
的等效选项是-r
。