ファイル内のすべての空行を削除しようとしていますが、空でない各行の後に「\ n」を保持したいと思います。
問題:CLIで使用するとコマンドは正常に機能しますが、bashスクリプトでコマンドを使用するたびにすべての「\ n」が削除されるため、すべての結果を別々の行に置くのではなく1行に入れます。
これは私のコードです。
#printing second and third word from every line and remove lines that do not contain any digits
result=$(cat "$output_file" | awk '{print $2" "$3}' | sed 's/[^0-9]*/\\n/')
echo -e ""$result"" > "$output_file"
#getting rid of all empty lines but what happens is that the whole file becomes one line
no_empty_lines=$(cat "$output_file" | awk NF)
echo -e ""$no_empty_lines"" > "$output_file"
編集するファイル:
>135.121.62.246 7.4 >135.121.160.65 7.8 >135.121.106.56 7.5 > > >135.121.106.96 6.2 > > >135.121.160.106 10 > >135.121.90.46 コマンド失敗
要求された結果:
編集するファイル:
>135.121.46.246 7.4 >135.121.106.46 7.8 >135.121.106.56 7.5 >135.121.106.96 6.2 >135.121.160.16 10 >135.121.90.46 コマンド失敗
答え1
1つ以上の文字を含む行を一致させることができます。
grep . {file}
関連ファイルを置き換えるコードに入れます。一時ファイルを作成して作成が成功したら、元のファイルを一時ファイルに置き換えます。最後に、元のファイルが正常に置き換えられなかった場合は、一時ファイルを削除します。
file=some_file.txt
grep . "$file" >"$file.tmp.$$" && mv -f "$file.tmp.$$" "$file"
rm -f "$file.tmp.$$"
ところで、これが元のコードで改行文字が失われる理由です。
result=$(cat "$output_file" | awk '{print $2" "$3}' | sed 's/[^0-9]*/\\n/') echo -e ""$result"" > "$output_file"
変数$result
に改行を含むテキストが正しく含まれています。 (これは非効率的な生産ラインですが、作業中は問題を無視します。)
ところで、このecho
行が本当に変です。あなたがそこにいる理由を理解できません""
。長さ0の引用符で囲まれた文字列を表し、次のように効果的に削除できます。
echo -e $result > "$output_file"
その後、シェルは内容を評価し、$result
スペース文字列を単一のスペースに変換します。この場合、タブ改行文字空白として扱われます。 (hello whole\nworld
で読んでくださいhello whole world
。)
変数を二重引用符で囲むと、この問題は発生しません。
echo -e "$result" > "$output_file"
答え2
あなたのコードが改善されました:
awk -i inplace '$2 ~ /[0-9]/ || $3 ~ /[0-9]/ { print $2, $3 }' "$output_file"
awk
これはGNU 4.1.0以降(このオプションの場合)を使用すると仮定します-i inplace
。このコードは、1つ以上のフィールドに数字を含む行から2番目と3番目のフィールドを抽出します。
GNUなしawk
:
tmpfile=$(mktemp)
cp "$output_file" "$tmpfile"
awk '$2 ~ /[0-9]/ || $3 ~ /[0-9]/ { print $2, $3 }' "$tmpfile" >"$output_file"
rm -f "$tmpfile"
このプログラムを異なる方法で表現する方法は、2番目と3番目のフィールドをawk
リセットして$0
から数字をテストすることです。
awk -i inplace '{ $0 = $2 " " $3 }; /[0-9]/' "$output_file"
コードには多くの問題があります。あなたが直接言及したもの、すべての行が1行で終わるのは、引用符で囲まれてい$result
ない値を使用するためですecho
。$result
何らかの理由で拡張の両側に2つの二重引用符(2つの空の文字列)を使用しているため、拡張に引用符はありません""$result""
。
引用符なしで変数拡張を使用すると、シェルは変数値を取得し、スペース、タブ、または改行に分割して複数の単語を作成します。これにより、各単語にファイル名がワイルドカードとして追加されます。その後、生成された単語は、各引数echo -e
の間にスペースがあり、末尾に改行文字を持つ各引数を出力するコードで使用されます。
また、コマンドの出力を変数に入れる必要はありません。この場合は、ファイルにリダイレクトするだけです。
コマンドは、sed
各行の先頭に文字列を挿入して、行\n
の最初の行にある数字以外のすべての項目を置き換えます。数字を含まない行は削除されません。これを行うには、sed
式を使用してください/[0-9]/!d
。ただし、数値を含むスクリプト行のみを出力する限りawk
(上記のコードで実行する操作)、これを行う必要はありません。
驚くべきことに、配管入力awk
やsed
その逆の場合はそれほど一般的ではありません。やることは十分ですawk
。sed
答え3
コードの問題は、結果をbash
変数に保存することです。
no_empty_lines=$(cat "$output_file" | awk NF)
その中(重複をスキップするcat
)は次のように見えます。
result=$(command that returns multi-line data)
ただし、bash
複数行の文字列をスペースを含む1行に変換してください。
可能な方法は次のとおりです。ここ- これがあなたに必要なものだと思いますが、以下を使用してくださいbash
。
no_empty_lines=( $(awk 'NF' "$output_file") )
現在の項目は${no_empty_lines[0]}
、、、${no_empty_lines[1]}
...です。
ループで呼び出す
for ((i=0;i<=${#no_empty_lines[@]}-1;i++)) ; do echo ${no_empty_lines[i]} ; done
繰り返しますが、これはコードが失敗する理由を示すためですbash
。上記のスレッドのオプションの1つを使用することをお勧めします。返品:この配列はすべての単語を配列の別の要素に配置するため、入力の改行構造が完全に削除されます。
答え4
@roaimaの助けを借りて問題を絞り込むことができ、
あなたの答えでは、結果は複数行のデータを正しく保存します。印刷すると問題が発生します。変数が引用されていないため(rcho ""$result""はecho $resultと同じです)、シェルは結果を複数の単語に解析し、改行文字は他の空白のように扱われます。 – Emma Luo 6時間前
したがって、考えられる解決策は次のとおりです。
result=$(cat "$output_file"| awk '{print $2" "$3}' | sed 's/[^0-9]*//')
echo -e "$result" | awk NF > "$output_file"
変数が正しく保存されたとし、「$result」をエコーし、「awk NF」にパイピングして空行を削除し、ファイルに出力するときに追加の引用符を削除しました。
これで結果は次のようになります。
>135.121.9.256 6.2 >135.121.160.50 7.5 >135.121.106.10 10 >135.121.9.66 コマンドの失敗 >135.121.100.156 コマンドの失敗