sedコマンドを使用して特定の行が存在するかどうかを確認し、存在しない場合は追加します。

sedコマンドを使用して特定の行が存在するかどうかを確認し、存在しない場合は追加します。

ファイル にさらに端末を追加したいと思います。より具体的には、 (は範囲内)が存在しない場合は )/etc/securettyを追加したいと思います。これはコマンドで可能ですか? 以下は、 の内容です。pts/nn0-9sed/etc/securetty

# Local X displays (allows empty passwords with pam_unix's nullok_secure)
pts/0
pts/1
pts/2
pts/3

私は次のようなことを試しました:

sudo sed '+pts/3+a pts/4' /etc/securetty

次のエラーが発生します。

sed: -e expression #1, char 3: extra characters after command

答え1

対応する行に出会ったら、pts/ 番号を書き留めます。-pオプションは行になりますautoprint。 に到達したら、eofハッシュを取り出し%h、フィルターに渡して、どの端末が印刷されなかったかを判断し、それが起こるようにフォーマットを準備するためにgrep使用します。map

perl -lpe 'm|^pts/([0-9])$| and $h{$1}++;
   END{ print for map { "pts/$_" } grep { !$h{$_} } 0 .. 9; }
' /etc/securetty

hold spaceを0 1 2 ... 9 の数字で初期化します。pts/[0-9]行に遭遇するたびに、これをホールド スペースから切り取ります。 ではeof、ホールド スペースを取得し、数字が見つかった場合は、 を適切な形式に調整して出力します。

sed -e '
   # initialize the hold space with 0 1 ... 9
   1{x;s|.*|'"$(echo {0..9})"'|;x}

   # whatever be the line, it needs to be printed
   p

   # we meet a valid pts/ line
   \|^pts/[0-9]$|{
      # the hold space gets appended to the pattern space
      G
      # grab what is the pts number and search for it in the hold and
      # delete itand store back the changes into hold space.
      s|^pts/\([0-9]\)\n\(.*\)\1 |\2|;h
   }

   # weve not arrived at the eof and weve processed the input so go no further
   $!d

   # we are at the eof, so we bring back the hold space. just in case all
   # numbers were dealt with up, we simply bail out. Else, prepend the str 
   # pts/ to the numbers present and simply were home
   g;/[0-9]/!d;s/ //g
   s|[0-9]|pts/&\n|g;s/.$//

   # *TIP*: Sprinkle the l, list pattern space at various places to see 
   # whats going on.

' /etc/securetty 

答え2

欠落している行を 1 行追加するには、出現する各行を削除し、最後に追加します。

sed -n '/pattern/!p;$a pattern'

しかし、それを 10 パターン繰り返すのは面倒です。

sed '/pts\/[0-9]/d;$a pts/0 ...

最後の行を削除すると失敗します。つまり、逆に、最初の行だけが で始まると仮定します#

sed '/#/a pts/0\
pts/1\
pts/2\
pts/3\
pts/4\
pts/5\
pts/6\
pts/7\
pts/8\
pts\9
/pts\/[0-9]/d'

ひどいですね。この場合は別のツールを使用することをお勧めします。

答え3

任意の行またはすべてのpts/N行を削除し、すべてを再度追加します。

{ grep -xv '^pts/[0-9]$' /etc/securetty; printf 'pts/%d\n' {0..9}; } > /etc/securetty.new
cat /etc/securetty.new
mv /etc/securetty.new /etc/securetty

お気に入りのテキスト処理ツールを使ってこれを一度に行うこともできます。ed

ed -s /etc/securetty <<IN
g/^pts\/[0-9]$/d
.r ! printf pts/\%d\\\n {0..9}
,p
q
IN

(その場で編集するには を置き換えてください),pまたはwsed

{ printf '%s\\\n' '$a' pts/{0..8}
printf '%s\n' 'pts/9' '/^pts\/[0-9]$/d'
} | sed -f- /etc/securetty

プレーンとほぼ同じです

sed '$a\
pts/0\
pts/1\
pts/2\
pts/3\
pts/4\
pts/5\
pts/6\
pts/7\
pts/8\
pts/9
/^pts\/[0-9]$/d' /etc/securetty

(使用sed -iファイルをその場で編集する)

答え4

sedファイルは行ごとに処理されるため、行をまたいで情報を「記憶」することは非常に困難です。

grepを使用すると、ファイルに特定のパターンが含まれているかどうかを確認できます。 を使用すると-f、複数のパターンを同時に指定できます。次のコードは、完全なリストpts/0..を生成しpts/9、指定されたファイルにすでに存在するパターンを削除して、残りのパターンをファイルに追加します。

#!/bin/bash
printf 'pts/%d\n' {0..9} \
| grep -vFf "$1"  - >> "$1".new
mv "$1".new "$1"

関連情報