我知道有几个不同的开放和回答,但我的有点不同。我试图在bash中这样做。
我有这个文件:
Line1 asd asd asd \
asd asd asd \
Line2 asd asd asd \
asd asd asd \
Line3 asd asd asd \
asd asd asd \
Line4 asd asd asd \
asd asd asd \
我想要的输出是:
Line1 asd asd asd asd asd asd
Line2 asd asd asd asd asd asd
Line3 asd asd asd asd asd asd
Line4 asd asd asd asd asd asd
因此,作为bash循环更容易阅读。什么命令可以让我这样做?
提前致谢。
答案 0 :(得分:3)
Perl解决方案:
perl -pe 's/\\$// and chomp' < input > output
s///
是替代品。 \\
匹配反斜杠,$
匹配行尾。chomp
删除一个尾随换行符(如果存在)。要删除前导空格,请使用
's/^ +//; s/\\$// and chomp'
^
匹配行首。 +
匹配一个或多个空格。代替。
答案 1 :(得分:3)
当您不使用read
时,bash内置-r
支持反斜杠 - 续行(其他当您需要此支持时,您总是应该使用-r
)
所以应该从文件/ etc中读取这些行。正好。 (假设他们没有其他反斜杠转义序列,需要保留它们。
$ while IFS= read line; do
echo "[$line]"
done < <(printf 'Line1 asd asd asd \
asd asd asd \
Line2 asd asd asd \
asd asd asd \
Line3 asd asd asd \
asd asd asd \
Line4 asd asd asd \
asd asd asd \
')
[Line1 asd asd asd asd asd asd ]
[Line2 asd asd asd asd asd asd ]
[Line3 asd asd asd asd asd asd ]
答案 2 :(得分:1)
注意:
\r\n
)。但是,鉴于此问题尚未说明,此处的解决方案仅匹配 Unix 式(\n
)。要匹配\r\n
行结尾,请将\n
替换为'"$(printf '\r')"'\n
(原文如此),或者在bash
中'$'\r''\n
替换sed
命令。 (使用 GNU sed,您只需使用\r\n
,但POSIX sed
不会将\r
识别为转义序列。 更正后的OP's own solution 版本,该版本还处理以\
结尾的行,这些行正确地在空行之前。
sed -e ':a' -e '$!{N;ba' -e '}; s/ \\\n[[:blank:]]*/ /g' filename
-e ':a' -e '$!{N;ba' -e '}'
是一种常见的sed
习语:一个循环,将所有输入行一次读入模式空间(输入缓冲区) - BSD sed
需要多个-e
选项才能使其正常工作(或者,多行脚本)。
\
的最后换行符之前,这是不常见的,并且会导致\
未被删除;如果你确实需要处理这种情况,请在G;
之前插入s/.../.../
,这会有效地将另一个换行添加到模式空间,从而导致最后一个\
被删除。 s/ \\\n[[:blank:]]*/ /g
然后对所有输入行进行操作,全局(g
)替换单个空格的运行,后跟\
(
{{1 }),后跟换行符(\\
),后跟任意数量的空格和/或制表符。 (\n
),并用一个空格([[:blank:]]*
)替换每个此类运行
简而言之:在行末尾的
导致该行与 next 行连接,删除尾随<space>\
并从下一行中删除前导空格。 注意:
\
和awk
两种风格。sed
解决方案更受欢迎,因为他们不会同时读取所有输入,这对于大文件可能会有问题。 (可以说,它们也更容易理解。)awk
)来保留未修改的字符串;在没有引用<<'EOF'
的情况下, shell 自己的字符串文字处理将解析嵌入的行继续并在命令看到字符串之前连接行。这些解决方案只需删除 EOF
序列,然后按加入行 no separator < / em>的;例如,这是\<newline>
默认执行的操作。
但是,与read
相比,这些解决方案有两个优势:
read
实例不受影响。\
和sed
的速度要快得多,只需要几条输入线。awk
解决方案:awk
awk '/\\$/ { printf "%s", substr($0, 1, length($0)-1); next } 1' <<'EOF'
Line1 starts here\
and ends here.
Line2 starts here, \
continues here,\
and ends here.
EOF
Line1 starts here and ends here.
Line2 starts here, continues here, and ends here.
匹配行末(/\\$/
)的\
,表示信号行延续。$
从输入行substr($0, 1, length($0)-1)
中删除尾随\
。$0
,打印(修改后的)当前行没有尾随换行符,这意味着接下来的任何打印命令都将直接附加到它,有效地加入当前行和下一行。printf "%s"
完成当前行的处理。next
是一种常见的1
成语,是awk
的简写,即只是打印输入行(尾随{ print }
)。\n
解决方案:sed
请注意最后一行中的两个 double 空格,因为会保留所有空格。
$ sed -e ':a' -e '$!{N;ba' -e '}; s/\\\n//g' <<'EOF'
Line1 starts here\
and ends here.
Line2 starts here, \
continues here,\
and ends here.
EOF
Line1 starts here and ends here.
Line2 starts here, continues here, and ends here.
)解决方案:以下解决方案诱人简单,但不完全健壮并且安全风险:可能会导致执行任意命令:
bash
这些解决方案规范化空白,如下所示:删除# Store input filename, passed as the 1st argument,
# in variable $file.
file=$1
# Construct a string that results in a valid shell command containing a
# *literal* here-document with *unquoted* EOF delimiter 0x3 - chosen so
# that it doesn't conflict with the input.
#
# When the resulting command is evaluated by `eval`, the *shell itself*
# performs the desired line-continuation processing, BUT:
# '$'-prefixed tokens in the input, including command substitutions
# ('$(...)' and '`...`'), ARE EXPANDED, therefore:
# CAUTION: Maliciously constructed input can result in
# execution of arbitrary commands.
eval "cat <<$(printf '\3')
$(cat "$file")"
之前的任何尾随空格,以及 next 行中的空白空格;然后,生成的行通过单个空格 连接
后者将这些解决方案与choroba's Perl solution
\<newline>
解决方案awk
awk '
contd { contd=0; sub(/^[[:blank:]]+/, "") }
/\\$/ { contd=1; sub(/[[:blank:]]*\\$/, ""); printf "%s ", $0; next }
1' <<'EOF'
Line1 starts here \
and ends here.
I am a loner.
Line3 starts here, \
continues here, \
and ends here.
EOF
Line1 starts here and ends here.
I am a loner.
Line3 starts here, continues here, and ends here.
(在布尔上下文中默认为0 / false)用作标志,以指示前一行是否用尾随contd
表示行继续。\
),它会立即重置(尽管如果继续行继续在下一行继续,它可能会再次设置在下面),并且从中删除前导空格当前行(contd
);请注意,未指定目标变量作为第3个参数隐式地以整个输入行sub(/^[[:blank:]]+/, "")
。$0
匹配行末(/\\$/
)的\
,信令行延续。
$
),contd=1
之前跟踪空格(\
以及sub(/[[:blank:]]*\\$/, "")
本身\
提供。printf "%s "
然后进入下一个输入行,而不处理当前行的其他命令。next
是一种常见的1
成语,是awk
的简写,即简单地打印输入行(尾随{ print }
);请注意,在两种情况下达到此打印命令:
\n
解决方案sed
对于连续中涉及的行,将行尾和行开始空格标准化为单个空格。
请注意如何不修改没有尾随$ sed -e ':a' -e '$!{N;ba' -e '}; s/[[:blank:]]*\\\n[[:blank:]]*/ /g' <<'EOF'
Line1 starts here \
and ends here.
I am a loner.
Line3 starts here, \
continues here, \
and ends here.
EOF
Line1 starts here and ends here.
I am a loner.
Line3 starts here, continues here, and ends here.
的行。
答案 3 :(得分:1)
$ awk -v RS= '{gsub(/\s*\\\s*/,"")}1' file
Line1 asd asd asd asd asd asd
Line2 asd asd asd asd asd asd
Line3 asd asd asd asd asd asd
Line4 asd asd asd asd asd asd
如果您没有GNU awk,请使用[[:space:]]
代替\s
。
请注意,只要你在shell中编写一个循环只是为了操作文本你就会有错误的方法,所以做上述准备以简化bash读取循环可能是一个坏主意。
答案 4 :(得分:-1)
修改
此命令将删除下一行的空格,反斜杠和制表符。
sed ':a;N;$!ba;s/ \\\x0D\x0A\x09/ /g' filename
line1 asd asd asd \
asd asd asd
到
line1 asd asd asd asd asd asd
然后我可以使用:
sed '/^[[:space:]]*$/d' filename
删除这些文件行之间的空格