根据外部或内部单引号替换不同的空格

时间:2016-10-26 15:08:07

标签: regex perl awk sed quotes

我的输入有一些字段

  • 以空格分隔,
  • 其他一些用引号括起来,也用空格分隔

以下是输入示例:

active=1 'oldest active'=0s disabled=0 'function call'=0

我想替换:

  • 引号外的所有空格|
  • 所有内部引用_

输出将是:

active=1|'oldest_active'=0s|disabled=0|'function_call'=0

我尝试使用网络上找到sedperl的不同解决方案,但没想成功。

6 个答案:

答案 0 :(得分:2)

$ s="active=1 'oldest active'=0s disabled=0 'function call'=0"
$ echo "$s" | perl -pe "s/'[^']*'(*SKIP)(*F)| /|/g; s/ /_/g"
active=1|'oldest_active'=0s|disabled=0|'function_call'=0

两步替换:

  • 首先,'[^']*'(*SKIP)(*F)将跳过'所包围的所有模式,并用|
  • 替换剩余的空格
  • 其次,'内的空格将替换为_


替代解决方案:

$ echo "$s" | perl -pe "s/'[^']*'/$& =~ s| |_|gr/ge; s/ /|/g"
active=1|'oldest_active'=0s|disabled=0|'function_call'=0
  • 灵感来自this answer
  • '[^']*'/$& =~ s| |_|gr/ge使用另一个替换命令替换匹配模式'[^']*'中的所有空格。 e修饰符允许在替换部分
  • 中使用命令而不是字符串
  • 然后使用s/ /|/g
  • 处理剩余的空格


进一步阅读:

答案 1 :(得分:1)

使用gnu awk FPAT,您可以这样做:

s="active=1 'oldest active'=0s disabled=0 'function call'=0"

awk -v OFS="|" -v FPAT="'[^']*'[^[:blank:]]*|[^[:blank:]]+" '{
   for (i=1; i<=NF; i++) gsub(/[[:blank:]]/, "_", $i)} 1' <<< "$s"

active=1|'oldest_active'=0s|disabled=0|'function_call'=0
  • FPAT正则表达式中,我们使用轮换来创建所有单引号值的字段+非空格值,即'[^']*'[^[:blank:]]*或非空白值,即来自输入的[^[:blank:]]+
  • 使用gsub我们只需用_替换所有空格,因为我们只会在所有字段中的单引号内获取空格。
  • 最后使用OFS='|'我们使用|
  • 分隔输出

参考: Effective AWK Programming

答案 2 :(得分:1)

这可能适合你(GNU sed):

sed -r ":a;s/^([^']*('[^ ']*')*[^']*'[^' ]*) /\1_/;ta;y/ /|/" file

首先用_替换引用字符串中的所有空格,然后将剩余的空格转换为|

答案 3 :(得分:1)

@ anubhava的解决方案让人想起老派的perl解决方案:

$ echo $s | perl -047 -pe "(\$.%2)?s/ /|/g:s/ /_/g;"
active=1|'oldest_active'=0s|disabled=0|'function_call'=0

用单引号(047)划分线,并基于偶数/奇数划分。

答案 4 :(得分:0)

我们可以在循环中使用正则表达式。

$str = "active=1 'oldest active'=0s disabled=0 'function call'=0";
print "\nBEF: $str\n";
$str =~s#active=1 'oldest active'=0s disabled=0 'function call'=0# my $tmp=$&; $tmp=~s/\'([^\']*)\'/my $tes=$&; $tes=~s{ }{\_}g; ($tes)/ge; $tmp=~s/ /\|/g; ($tmp); #ge;
print "\nAFT: $str\n";

除此之外,可能会有一些简短的方法。

答案 5 :(得分:0)

from turtle import Turtle, Screen
from random import seed, randint

seed()

DELAY = 100  # milliseconds

# setup the output window
picSize = (400, 600)
playGround = Screen()
playGround.screensize(*picSize)

# setup the turtles
bob = Turtle(shape='turtle', visible=False)
bob.penup()
bob.color('red')
bob.speed('slow')

jeff = Turtle(shape='turtle', visible=False)
jeff.penup()
jeff.color('blue')
jeff.speed('normal')

x_quadrant = -picSize[0] // 2, picSize[0] // 2
y_quadrant = -picSize[1] // 2, picSize[1] // 2

# find random positions for the turtles
jeff_xy = randint(*x_quadrant), randint(*y_quadrant)
bob_xy = randint(*x_quadrant), randint(*y_quadrant)

# find a point to move bob to and rotate towards its target location
bobNew_xy = randint(*x_quadrant), randint(*y_quadrant)
bob.setheading(bob.towards(bobNew_xy))

# place the turtles and show them
jeff.setpos(jeff_xy)
jeff.showturtle()
jeff.pendown()

bob.setpos(bob_xy)
bob.showturtle()
bob.pendown()

# bob's motion is in a straight line
def moveStraight():
    bob.fd(bob.speed())
    playGround.ontimer(moveStraight, DELAY)

# jeff's motion is towards bob
def moveToward():
    if bob.position() != jeff.position():
        jeff.setheading(jeff.towards(bob))
        jeff.fd(jeff.speed())
    playGround.ontimer(moveToward, DELAY)

moveStraight()
moveToward()

playGround.exitonclick()