単一の改行のみを置き換えるより良い方法が必要ですか?


27

私は通常LaTexにコンパイルするため、または改行が無視される他の形式で書くので、私は文ごとに1行を書く習慣があります。空白行を使用して、新しい段落の開始を示します。

これで、このスタイルで記述されたファイルがあり、プレーンテキストとして送信したいだけです。単一の改行をすべて削除したいが、二重の改行はそのままにしておきたい。これは私がやったことです:

sed 's/$^/NEWLINE/' file.txt | awk '{printf "%s ",$0}' | sed 's/NEWLINE/\n\n/g' > linebreakfile.txt

これは空の行をファイルに表示されないと確信しているいくつかのテキストで置き換えます:NEWLINEそして、それはawkですべての改行を取り除きます(いくつかのウェブサイトでそのトリックを見つけました)そして、NEWLINEsを必要な2つの改行で置き換えます。

これは非常に単純なことを行うための長い方法のようです。もっと簡単な方法はありますか?また、複数のスペース(何らかの理由で時々入り込む)を単一のスペースに置き換える方法があれば、それも良いでしょう。

私はemacsを使用しているので、いくつかのemacs固有のトリックがあれば良いのですが、純粋なsedバージョンまたは純粋なawkバージョンが必要です。


最初のsedコマンドでは、$ ^ではなく^ $を意味しました。
ユーザー不明

@userはい、そうです。
シーマス

すべての改行を削除する簡単な方法:tr -d "\n"
jfg956

回答:


18

次のようにawkを使用できます。

$ awk ' /^$/ { print; } /./ { printf("%s ", $0); } ' test

または、最後に余分な改行が必要な場合:

$ awk ' /^$/ { print; } /./ { printf("%s ", $0); } END { print ""; } ' test

または、改行で段落を区切る場合:

$ awk ' /^$/ { print "\n"; } /./ { printf("%s ", $0); } END { print ""; } ' test

これらのawkコマンドは、パターンによって保護されているアクションを使用します。

/regex/

または

END

次のアクションは、パターンが現在の行と一致する場合にのみ実行されます。

また、^$.文字は正規表現で特別な意味を持ち^、行の先頭$、末尾、および.任意の文字に一致します。


これは良いことですが、段落間の空の行を維持したいです。最初の印刷コマンドのどこかに新しい行を追加することで、このようなことができると思いますか?また、何を/./やっている:それelse/^$/文字列の一致のように動作しているようだ、それは正しいですか?
シーマス

1
@Seamus、確かに-ちょうど最初の印刷を置き換えます(答えを更新しました)-/./は少なくとも1文字の長さのすべての行に一致します。つまり、空行のみに一致する/ ^ $ /パターンの補数です。
maxschlepzig

9

AwkまたはPerlの段落モードを使用して、ファイルを段落ごとに処理します。段落は空白行で区切られます。

awk -vRS= '
  NR!=1 {print ""}      # print blank line before every record but the first
  {                     # do this for every record (i.e. paragraph):
    gsub(" *\n *"," "); # replace newlines by spaces, compressing spaces
    sub(" *$","");      # remove spaces at the end of the paragraph
    print
  }
'
perl -000 -pe '             # for every paragraph:
  print "\n" unless $.==1;  # print a blank line, except before the first paragraph
  s/ *\n *(?!$)/ /g;        # replace newlines by spaces, compressing spaces, but not at the end of the paragraph
  s/ *\n+\z/\n/             # normalize the last line end of the paragraph
'

もちろん、これは(La)TeXを解析しないので、コメント、逐語的な環境、その他の特別な構文を恐ろしく破壊します。DeTeXまたは他の(La)TeXからテキストへのコンバーターを調べてください


8

セッドソリューション

$ sed -e ':a;N;$!ba;s/\(.\)\n/\1 /g' -e 's/\n/\n\n/' test.text

このソリューションで:aは、aコマンドを使用せずにラベルを作成することに注意してください。

複数のスペースを置き換える

使用tr$ tr -s ' ' <test.text


8

正しく理解できた場合、空の行は2つの連続した改行を意味し\n\nます。

もしそうなら、1つの可能な解決策は、改行のすべての特異な出現を排除することです。

Perlでは、先読みアサーションはこれを達成する1つの方法です。

$ perl -0777 -i -pe 's/\n(?=[^\n])//g' test
  • この-0777フラグは、ファイル全体を単一の文字列に効果的に丸lurみします
  • -p デフォルトで動作している文字列を印刷するようにperlに指示します
  • -i インプレース編集を指定します
  • グローバルマッチングにより、すべての単一改行の処理が保証されます。

これが抱える問題の1つは、文の間にスペースがないことです。
スティーブンD

6

(古代の質問の復活)

これはまさに何でfmtあり、何のためにあるようparです-段落の再フォーマット。あなたのように(そして多くのプログラムのように)、段落の境界を1つ(または複数)の空白行として定義します。これらのいずれかを介してテキストをパイピングしてみてください。

fmt 標準のUNIXユーティリティであり、GNU Coreutilsにあります。

parは、fmtAdam M. Costelloによって書かれた非常に強化されたもので、http: //www.nicemice.net/par/にあります(debianを含むいくつかのディストリビューション用にパッケージ化されています-1996年1月にdebian用にパッケージ化しました。 pkgの新しいメンテナがいますが。)


6
sed -e'/./{H;$!d;}' -e'x;s/\n//g'

sedH少なくとも1文字を含む古いスペースに行を追加します。dおそらく最後のものを除いて、それらはすべて、すぐに劇場に座ります。残る唯一の行は空白で、sede xが保留スペースとパターンスペースを変更し、蓄積されたすべての\newline文字を削除するとき、これらの行にあります。

<tabs>または<spaces>のみを含む行を空白と見なす場合は、/./上記のアドレスをに置き換えます/[^[:blank:]]/。スペースを絞るには:

 sed -e'/./{H;$!d;}'    \
     -e'x;s/\n//g'      \
     -e's/\([[:blank:]]\)*/\1/g'

5

Gillesのperlとawkのコンパクトな例を見た後、これを投稿したがりませんでしたが、私は既に演習を行っていました。この点だけでも興味があるかもしれません..(コメント付き!)

このスクリプトは、空白行が含まれている場合でも、空白行を空白と見なします。
テキスト内の複数のスペースは、単一のスペースに凝縮されます。
末尾の空白はテキスト行から削除されます。連続する空白行は1行に折りたたまれます。スクリプトは、上部と下部の空白行をそのまま残します。

最も些細なスクリプト以外の場合は、sedを別のスクリプトファイルとして構造化された形式で簡単に記述できます。以下にその例を示します。

拡張正規表現構文
呼び出しを使用:$ sed -rf script text-file

  :first-empty-line
  #================
  /^[[:space:]]*$/ { # if pattern-space is empty...
      $q  # last line # flush-quit 
      n   # pattern-flush=nextline-continue

      :subsequent-empty-line
      #=====================
      /^[[:space:]]*$/ { # if pattern-space is empty...
          $d        # last line # pattern-delete-cycle
          N         # pattern+=nl+nextline
          s/.*\n//  # scrap the leading 'blank' line
          t subsequent-empty-line # branch-on-substitute
      }
  }

  :text-line
  #=========
  $q                       # last line # flush-quit 
  s/^(.*)[[:space:]]*/\1/  # trim trailing whitespace
  s/ +/ /g                 # condense mulltiple spaces
  N                        # pattern+=nl+nextline
  /^.*\n[[:space:]]*$/ { # if newly-read line is blank 
      P          # pattern-first-line-print
      s/^.*\n//  # remove the leading 'text' line
      t first-empty-line   # branch-on-substitute
  }
  # read line is text
  s/\n/ /      # replace \n with a space
  t text-line  # branch-on-substitute

注:flushコメント内のの意味は、次のとおりです。パターンスペースをsedの内部stdout処理に送信します。stdoutへの明確な印刷を意味するものではありません。出力はsedの-nオプションに依存します。例えば。q指令手段のフラッシュが終了しないとこれら二つのスニペットを比較...:echo x |sed -e qプリントは、X、echo x |sed -ne q印刷物の何を使用して、一方pに応じて、二回または一回の「x」に印刷するコマンドを-nオプション。


良いコメントのために+1。コメントがまったくないプログラムがあまりにも多く見られました。
デビッドケーリー

4

sedすべての行をsedの「ホールドスペース」に連結して、パターンマッチングのために「パターンスペース」に最終的にコピーされる1つの長い文字列を取得する別のソリューションを次に示します。

改行はsed「パターンスペース」の最後の長い文字列に保持されるため、二重改行に関する空行[^\n]\n\n[^\n]はに一致して変更できます[^\n]\n[^\n]

詳細については、たとえばsedおよびMulti-Line Search and Replaceを参照してください。

text='
line 1

line 2
line 3





line 4


line     5



line 6
line 7

line 8
'

# FreeBSD sed
# first sed deletes first / last line if empty and squeezes multiple spaces
printf '%s' "$text" |
sed -e '1{/^$/d;}' -e '${/^$/d;}' -e '/[[:space:]]\{2,\}/s// /g' | 
sed -n -e '1h;1!H;${;g;/\([^[:cntrl:]]\)\n\n\([^[:cntrl:]]\)/s//\1\
\2/g;p;}' |
nl -b a


# GNU sed
# alternative using ...;x;... instead of ...;g;...
# cf. man sed | less -p '\]x'
printf '%s' "$text" |
gsed -e '1{/^$/d;}' -e '${/^$/d;}' -e '/[[:space:]]\{2,\}/s// /g' | 
gsed -E -n '1h;1!H;${;x;/([^\n])\n\n([^\n])/s//\1\
\2/g;p;}' | 
nl -b a


# remove all the single linebreaks but leave the double linebreaks intact
printf '%s' "$text" | 
   sed -n -e '1h;1!H;${;g;/\([^[:cntrl:]]\)\n\([^[:cntrl:]]\)/s//\1 \2/g;p;}' | 
   nl -b a

3

これは古い学校かもしれません:

(echo ".pl 1" ; echo ".ll 80" ; echo ".ad l" ; cat your_file) | nroff

これにより、テキストが左揃え(.ad l)で出力され、行の長さが80(.ll 80)になります。ページ長オプション(.pl)は、ページ長1のページパディングを行うようにテキストプロセッサに指示するため、ページパディングは行われません。

すべての段落を1行で表示する場合は、次の項目に大きな数字を使用できます.ll

(echo ".pl 1" ; echo ".ll 1000000" ; echo ".ad l" ; cat your_file) | nroff

書式オプションの詳細については、man 7 groffを参照してください。


1

Emacsでは、これを時々使用しますregex

^J\([^^J]\) -> \1

手段:

改行ではない何かだけが続くすべての改行を、改行だけに置き換えます。そのようにして、段落内のすべての改行を取り除きますが、段落は保持します(二重改行)


0

auto-fill-modeon を使用すると、emacsは単純なユースケースでかなり良い仕事をすることがわかりM-qます。


動作の詳細は、auto-fill-modeアクティブになっているメジャーモードによって異なります。
dmckee
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.