Shell 脚本根据单行或多行中存在的开始和结束参数打印单行输出

Shell 脚本根据单行或多行中存在的开始和结束参数打印单行输出

我的文件是:

"abc"..,,xyz 123 "New york".."END" <- # Print this entire line as starts with " and ends with "END"
"mnh".....blahblah                 <- # dont print this line and hold til "END" is
"rew"..?/.."1324.75 United            # found and once it is found, merge multi-
 States"??..."END"                    # lines to single line without changes

期望的输出:

"abc"..,,xyz 123 "New york".."END"
"mnh".....blahblah"rew"..?/.."1324.75 United States"??..."END"    

发现下面的内容sed可以完成所有操作开始模式作为"结束模式as "END",但当中间行以";开头时它会中断这里当它开始于"rew"之前结束模式被发现。

sed -n '/^"/,/^"END"/{
        //!{H;/{x;s/\n\([^\n]*\)$/\1/;x}};
        /^"/{h};/"END"/{x;p};d
        }' file

关联:如何删除位于两个模式之间的每个记录的数据之间的换行符?

答案1

awk -v RS='"END"\n' -v FS='\n' -v ORS='"END"\n' -v OFS=' ' '{ $1=$1 };1' file

或同等的

awk 'BEGIN { ORS=RS="\"END\"\n"; FS="\n" } { $1 = $1 }; 1' file

OFS=' '(无论如何,它使用默认的事实)。

这是一个真的很短 awk命令,只需将输入从一组记录和字段分隔符重新格式化为另一组记录和字段分隔符。最神奇的是如何将输入记录和字段分隔符(RSFS)更改为新的输出分隔符(ORSOFS)。

您的输入文档,

"abc"..,,xyz 123 "New york".."END"
"mnh".....blahblah
"rew"..?/.."1324.75 United
States"??..."END"

"END"\n用作记录分隔符,并使用\n(换行符)作为字段分隔符。

将字段分隔符更改为(空格)足以解决您的问题。

实际上代码只是awk重新格式化记录,以便OFS使用新的字段分隔符 ( ) 代替旧的 ( FS)。

结果将是

"abc"..,,xyz 123 "New york".."END"
"mnh".....blahblah "rew"..?/.."1324.75 United States"??..."END"

从技术上讲,使用多字符值进行RS调用未指定行为根据awk实用程序的 POSIX 规范。大多数(全部?)当前awk实现将多字符值视为RS正则表达式。

答案2

如果一行不是以 sed 结尾,您可以将其连接到下一行,"END"如下所示:

sed -e :a -e '/"END"$/!N; s/\n//; ta' file

前任。给出file

"abc"..,,xyz 123 "New york".."END"
"mnh".....blahblah
"rew"..?/.."1324.75 United
States"??..."END"

然后

$ sed -e :a -e '/"END"$/!N; s/\n//; ta' file
"abc"..,,xyz 123 "New york".."END"
"mnh".....blahblah"rew"..?/.."1324.75 UnitedStates"??..."END"

请注意(与您想要的输出一致)这确实不是在进行连接时添加一个空格来代替换行符 - 如果您确实想要该空格,则只需更改s/\n//s/\n/ /

相关内容