次のファイルがあります。
###PSTERS###
LINE1
LINE2
###PSTADS###
LINE3
LINE4
###PSTEEE###
LINE5
LINE6
3つのファイルを作成する必要があります(ファイル名は私たちが検索するパターンです)。
PSTERS.txt:
LINE1
LINE2
PSTADS.txt:
LINE3
LINE4
PSTEEE.txt:
LINE5
LINE6
どうすればいいですか?次のスクリプトを試しましたが、awk構文エラーのため失敗しました。
#!/bin/bash
#This script will take 2 parameters as input.
# 1. Source File Path
# 2. Source File name as input
SOURCE_PATH=$1
SOURCE_FILE=$2
#Get the list of patterns we need to check from the Main source file
cd $SOURCE_PATH
pattern_list=`grep -e '^\#' $SOURCE_FILE | cut -d'#' -f4`
echo ${pattern_list}
#Split the Source File for each pattern in the variable pattern_list
for pattern in ${pattern_list}
do
cd $SOURCE_PATH
awk '/\#\#\#'$pattern'/{x='$pattern';next}{print > x;}' $SOURCE_FILE
done
答え1
非常に洗練されたアプローチを取っています。シェルスクリプトは必要ありません。以下はawk
1行のコードです。
awk '{if(gsub(/#+/,"")){name=$0;}else{print > name".txt"}}' file
これがgsub
「グローバル交換」です。したがって、上記の意味は、「行に行っている場合は#
その行を削除し(何も置き換えません)、変数「name」をその行の内容に設定します」を意味します。これで、その行#
は削除後に残りの内容になるため、name
パターンになります。その後、行がaと一致しない場合#
(代替が失敗した場合)、その行はname
aというファイルと現在の値で印刷されます.txt
。
それでもスクリプトをラップする必要がある場合は、次を使用してください。
#!/bin/bash -
#This script will take 1 parameter as input: the target file path
targetFile="$1"
targetDir=$(dirname -- "$targetFile")
targetFile=$(basename -- "$targetFile")
cd -P -- "$targetDir" || exit
awk '{if(gsub(/#+/,"")){name=$0;}else{print > name".txt"}}' < "$targetFile"
答え2
我々はrelative addressing
エディタを使用してed
これを行うことができます。
#
これには、最初のステップで入力ファイル内のすべての行の行番号を抽出することが含まれます。その後、ed
タスクを完了するための一連のコマンドを生成します。右側はsed
叙事詩が形象化した絵画空間の内容を示す。
sed -e '$s/.*/$/;$q;/^#/!d;=' inputfile |
sed -e '
N;N;h; # p.s.: 1\n###PSTERS###\n4$
s/^[1-9][0-9]*/&+/; /\$$/!s/$/-/; # p.s.: 1+\n###PSTERS###\n4-$
s/\n\(.*\)\n\(.*\)/,\2w \1.txt/; # p.s.: 1+,4-w ###PSTERS###.txt$
s/#//gp;g; # p.s.: 1+,4-w PSTERS.txt
s/.*\n/\n/; $!D; s/.*/q/
' |
ed -s - inputfile