回答:
より短くシンプルなsedソリューション:
sed '
: again
/\\$/ {
N
s/\\\n//
t again
}
' textfile
またはGNUを使用している場合はワンライナーsed
:
sed ':x; /\\$/ { N; s/\\\n//; tx }' textfile
sed
:私は理解し始めていると思います:)...あなたは各行をパターンスペースに直接追加し、「正常終了」行が来ると、パターンスペース全体が落ちて自動印刷されます(-nオプションがないため)... .. +1
sed -e :a -e '/\\$/N; s/\\\n//; ta'
これがawkソリューションです。行がで終わる場合、\
バックスラッシュを取り除き、改行を終了せずに行を印刷します。それ以外の場合、行を終了改行で印刷します。
awk '{if (sub(/\\$/,"")) printf "%s", $0; else print $0}'
これ自体は答えではありません。これはについての副次的な問題ですsed
。
具体的には、sed
それを理解するために、Gillesのコマンドを1つずつ分解する必要がありました...それについてメモを書き始め、それがここで誰かに役立つかもしれないと考えました...
そうここにある...ジルsedのスクリプト で文書フォーマット:
#!/bin/bash
#######################################
sed_dat="$HOME/ztest.dat"
while IFS= read -r line ;do echo "$line" ;done <<'END_DAT' >"$sed_dat"
foo bar \
bash \
baz
dude \
happy
yabba dabba
doo
END_DAT
#######################################
sedexec="$HOME/ztest.sed"
while IFS= read -r line ;do echo "$line" ;done <<'END-SED' >"$sedexec"; \
sed -nf "$sedexec" "$sed_dat"
s/\\$// # If a line has trailing '\', remove the '\'
#
t'Hold-append' # branch: Branch conditionally to the label 'Hold-append'
# The condition is that a replacement was made.
# The current pattern-space had a trailing '\' which
# was replaced, so branch to 'Hold-apend' and append
# the now-truncated line to the hold-space
#
# This branching occurs for each (successive) such line.
#
# PS. The 't' command may be so named because it means 'on true'
# (I'm not sure about this, but the shoe fits)
#
# Note: Appending to the hold-space introduces a leading '\n'
# delimiter for each appended line
#
# eg. compare the hex dump of the follow 4 example commands:
# 'x' swaps the hold and patten spaces
#
# echo -n "a" |sed -ne 'p' |xxd -p ## 61
# echo -n "a" |sed -ne 'H;x;p' |xxd -p ## 0a61
# echo -n "a" |sed -ne 'H;H;x;p' |xxd -p ## 0a610a61
# echo -n "a" |sed -ne 'H;H;H;x;p' |xxd -p ## 0a610a610a61
# No replacement was made above, so the current pattern-space
# (input line) has a "normal" ending.
x # Swap the pattern-space (the just-read "normal" line)
# with the hold-space. The hold-space holds the accumulation
# of appended "stripped-of-backslah" lines
G # The pattern-space now holds zero to many "stripped-of-backslah" lines
# each of which has a preceding '\n'
# The 'G' command Gets the Hold-space and appends it to
# the pattern-space. This append action introduces another
# '\n' delimiter to the pattern space.
s/\n//g # Remove all '\n' newlines from the pattern-space
p # Print the pattern-space
s/.*// # Now we need to remove all data from the pattern-space
# This is done as a means to remove data from the hold-space
# (there is no way to directly remove data from the hold-space)
x # Swap the no-data pattern space with the hold-space
# This leaves the hold-space re-initialized to empty...
# The current pattern-space will be overwritten by the next line-read
b # Everything is ready for the next line-read. It is time to make
# an unconditional branch the to end of process for this line
# ie. skip any remaining logic, read the next line and start the process again.
:'Hold-append' # The ':' (colon) indicates a label..
# A label is the target of the 2 branch commands, 'b' and 't'
# A label can be a single letter (it is often 'a')
# Note; 'b' can be used without a label as seen in the previous command
H # Append the pattern to the hold buffer
# The pattern is prefixed with a '\n' before it is appended
END-SED
#######
さらに別の一般的なコマンドラインツールはed
、デフォルトでファイルをその場で変更するため、ファイルのアクセス許可は変更されません(ed
詳細については、スクリプトからedテキストエディターでファイルを編集するを参照)。
str='
foo bar \
bash 1 \
bash 2 \
bash 3 \
bash 4 \
baz
dude \
happy
xxx
vvv 1 \
vvv 2 \
CCC
'
# We are using (1,$)g/re/command-list and (.,.+1)j to join lines ending with a '\'
# ?? repeats the last regex search.
# replace ',p' with 'wq' to edit files in-place
# (using Bash and FreeBSD ed on Mac OS X)
cat <<-'EOF' | ed -s <(printf '%s' "$str")
H
,g/\\$/s///\
.,.+1j\
??s///\
.,.+1j
,p
EOF
メモリ内のファイル全体をロードするsimple(r)ソリューション:
sed -z 's/\\\n//g' file # GNU sed 4.2.2+.
または、(出力)行の理解に役立つ(GNU構文)まだ短いもの:
sed ':x;/\\$/{N;bx};s/\\\n//g' file
1行(POSIX構文):
sed -e :x -e '/\\$/{N;bx' -e '}' -e 's/\\\n//g' file
または、awkを使用します(ファイルが大きすぎてメモリに収まらない場合):
awk '{a=sub(/\\$/,"");printf("%s%s",$0,a?"":RS)}' file
cppを使用できますが、出力をマージした空の行がいくつか生成され、sedで削除した導入部分があります-cpp-flagsとオプションでも同様に実行できます。
echo 'foo bar \
bash \
baz
dude \
happy' | cpp | sed 's/# 1 .*//;/^$/d'
foo bar bash baz
dude happy
cpp
は確かですか?あなたの例ではecho
、二重引用符で囲まれたwith文字列はすでに直線化されたテキストを出力しているのでcpp
、意味がありません。(これはsed
コードにも当てはまります。)文字列を一重引用符でcpp
囲むと、バックスラッシュが削除されるだけで、行は連結されません。(cpp
バックスラッシュの前にスペースがなければ連結は機能しますが、別の単語はセパレータなしで結合されます。)
cpp
それでもそのように使用すると、行が連結されません。の使用sed
は間違いなく不要です。使用cpp -P
:「-P
プリプロセッサからの出力でのラインマーカーの生成を禁止します。」– man cpp
cpp: “-P: No such file or directory cpp: warning: '-x c' after last input file has no effect cpp: unrecognized option '-P:' cpp: no input files
A cpp --version
が明らかにcpp (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3
-何ですか?Ubuntuはcppにパッチを適用していますか?どうして?私は、GNU ...読むことを期待しているだろう
cpp
実際に行を連結し、いくつかの空白を残します。さらに興味深いことに、同じバージョン4.4.3-4ubuntu5.1はここで受け入れます-P
。ただし、ラインマーカーが削除されるだけで、空の行は残ります。
cpp
:)