나는 다음과 같은 텍스트 줄을 만들었습니다.
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,,00:23:32:c2:a9:e8,Auth-Type,:=,Accept);
sed를 사용하여 다음과 같이 만들고 싶습니다.
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
이것은 맥락에서 더 의미가 있으며 지난 17시간 동안 (분명히) 이에 대해 더 많은 것을 배웠습니다.
#!/bin/bash
ssh [email protected] brmacs >>MACS.txt mv MACS.txt /etc/persistent scp [email protected]:/etc/persistent/MACS.txt MACS.txt
sed -i "1d" MACS.txt
head -c 58 MACS.txt >>shortmacs.txt
tail -c 18 shortmacs.txt >>usermac.txt
sed 's/"//g' usermac.txt >>usermacrdy.txt
sed -i 's/^/INSERT INTO `radcheck`(`id`, `username`, `attribute`, `op`, `value`) VALUES (,'',/' usermacrdy.txt
sed "s/$/','Auth-Type',':=','Accept');/" usermacrdy.txt > sqlquery.txt
sed -i "s/,,/\,\'\',\'/" sqlquery.txt
rm -f MACS.txt
rm -f shortmacs.txt
rm -f usermac.txt
rm -f usermacrdy.txt
일하다! ! !
헤더와 트레일러는 UBNT CPE 장치에서 전송된 원시 텍스트 파일에서 MAC 주소를 잘라낸 다음 sed를 통해 전달하여 MAC 주소 주위에 SQL 구문을 구축합니다.
id
결국 쿼리의 일부가 성공하는 데 필요하지 않다는 것을 알았 으므로 이제 약간 같은 상황에 있습니다.
sed -i 's/^/INSERT INTO `radcheck`(`username`, `attribute`, `op`, `value`) VALUES (/' usermacrdy.txt
sed "s/$/','Auth-Type',':=','Accept');/" usermacrdy.txt > sqlquery.txt
sed -i "s/\,\'\',\'//" sqlquery.txt
답변1
필요한 작은따옴표를 포함하는 방법에는 네 가지가 있습니다.
작은따옴표 문자열 내에서 작은따옴표 문자열을 이스케이프할 수 없습니다. 그러나 따옴표로 묶인 문자열을 끝내고 이스케이프된 작은 따옴표를 삽입한 다음 새 작은 따옴표로 묶인 문자열을 시작할 수 있습니다. 따라서 중간에 작은따옴표를 넣으려면 다음을 'ab'
사용하십시오 'a'\''b'
. 또는 필요한 sed 명령을 사용하십시오.
$ sed -r 's/,([^ ),]+)/,'\''\1'\''/g; s/,,/,'\'\'',/g' file
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
두 번째 방법은 큰따옴표로 묶인 문자열을 사용하는 것입니다. 이 경우 작은따옴표를 쉽게 삽입할 수 있습니다.
$ sed -r "s/,([^ ),]+)/,'\1'/g; s/,,/,'',/g" file
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
큰따옴표로 묶인 문자열의 문제점은 쉘이 이를 처리하는 방법입니다. 그러나 여기에는 쉘 활성 문자가 없으므로 쉽습니다.
세 번째 방법은 PM2Ring에 표시된 대로 16진수 이스케이프를 사용하는 것입니다.
의견에서 Jonathan Leffler가 제안한 네 번째 접근 방식은 sed
명령을 별도의 파일에 저장하는 것입니다.
$ cat script.sed
s/,([^ ),]+)/,'\1'/g
s/,,/,'',/g
$ sed -rf script.sed file
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
이 방법의 장점은 sed
쉘의 간섭 없이 명령을 직접 읽을 수 있다는 것입니다. 따라서 이는 쉘 활성 문자를 이스케이프할 필요를 완전히 없애고 명령을 순수 구문으로 입력할 수 있게 해줍니다 sed
.
솔루션 sed
작동 방식
요령은 원하는 쉼표로 구분된 문자열 주위에 작은따옴표를 붙이고 다른 문자열 주위에는 넣지 않는 것입니다. 제공하신 단일 예를 바탕으로 한 가지 접근 방식은 다음과 같습니다.
s/,([^ ),]+)/,'\1'/g
쉼표 뒤에 공백이 없고, 쉼표가 없고, 오른쪽 대괄호가 아닌 문자가 하나 이상 검색됩니다. 이러한 문자는 작은따옴표 안에 배치됩니다.
s/,,/,'',/g
연속된 쉼표를 찾아 그 사이에 두 개의 작은따옴표를 배치합니다.
OSX 및 기타 BSD 플랫폼
추가 백슬래시를 피하기 위해 위 sed
식에서는 확장 정규식을 사용합니다. GNU의 경우 로 호출되지만 -r
BSD의 경우 로 호출됩니다 -E
. 또한 일부 비 GNU는 sed
세미콜론으로 구분된 여러 명령을 허용하지 않습니다. 따라서 OSX에서는 다음을 시도해 보십시오.
sed -E -e "s/,([^ ),]+)/,'\1'/g" -e "s/,,/,'',/g" file
부록: MAC 주소 일치
의견을 통해 다음과 같은 정보를 얻을 수 있습니다.
$ cat file3
INSERT INTO radcheck(username, attribute, op, value) VALUES (00:23:32:c2:a9:e8,'Auth-Type',':=','Accept');
또한 여는 괄호 뒤의 MAC 주소 주위에 작은따옴표를 넣으려고 합니다. 이 작업을 수행할 수 있어야 합니다.
$ sed -r "s/\(([[:xdigit:]:]+)/('\1'/" file3
INSERT INTO radcheck(username, attribute, op, value) VALUES ('00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
모든 로캘의 [:xdigit:]
모든 16진수와 일치합니다 . 따라서 ([[:xdigit:]:]+)
MAC 주소(16진수 또는 콜론)가 일치합니다.
답변2
sed
글로벌 규모로 작업할 때는 읽는 방법에 대해 생각해야 합니다 . 부분 교체는 g
패턴 공간을 사용자의 사양에 따라 구분된 개별 필드로 나누어 각 필드에서 작동합니다. 구분 기호는 읽는 순서대로 왼쪽에서 오른쪽으로 인식되며, sed
각 작업은 최대한 빠르게 적용됩니다. 다음은 s///
원하는 작업을 수행하는 대체 명령문 입니다 .
sed "s/\(([^)]*)[^,]*\)\{0,1\},\([^,)]*\)/\1,'\2'/g
" <<\IN
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,,00:23:32:c2:a9:e8,Auth-Type,:=,Accept);
실행 시 다음을 인쇄합니다.
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
그게 다야 :
\(([^)]*)[^,]*\)\{0,1\}
*
- 가장 중요한 것은 0+일치 및 기타 유형의 분포입니다. 전체 블록은 선택 사항입니다.sed
기회가 주어지면 그 자리에 빈 문자열을 일치시킬 것입니다. 그리고 실제로 많은 시간 동안 그렇게 합니다. 그렇지 않으면 전혀 작동하지 않습니다. 하지만\{0,1\}
사용해본sed
결과아니요성냥더이와 같은 전체 시퀀스보다. 이래서 유통이 중요해요. 이 블록에는 다음이 있습니다.(
- 왼쪽 괄호가 하나 이상 있어야 합니다.[^)]*
- 0 + 오른쪽이 아닌 괄호.)
- 닫는 괄호[^,]*
- 0 + 쉼표가 아닙니다.
sed
\(
그룹화 되어 있으므로 순서대로 그리고 블록으로 각각 일치합니다\)
. 0*
+ 일치는매우전 세계적으로 중요 -+
이 설정에서 하나 이상을 사용하는 경우철저히애플리케이션 편집의 효율성을 줄입니다. 위 블록에 대한 입력의 경우sed
문자열을 다음과 같이 구분합니다.INSERT INTO radcheck
- 이 문자열이 옵니다.앞으로우리의 모든 일치 항목이 포함되어 있지 않습니다. 무시됩니다.(id, username, attribute, op, value) VALUES (
- 이 문자열은 전체*
선택적 일치 블록을 구성합니다. 먼저sed
와 일치하고 그 다음에(
는 then 의 전체 문자열, 그리고 마지막으로 중요한 것은 우리를 포함하는 전체 문자열입니다.[^)]*
)
[^,]*
초과하다의 또 다른 일치 사례입니다(
. 지금은 일치할 수 없으므로(
이 선택적 일치 그룹의 다음 항목을 건너뜁니다.sed
다음 것을 시도해 보겠습니다.
두 번째 시퀀스에 sed
대체를 적용 하면\2
(.,.,.)
아직\1
또한 대체품을 적용하십시오.여전히 일치 \1
. 나는 처음으로 다음 \1
과 같이 일치합니다.모두 (.,.,.)..(
차단하고 저장한 후 - 자체로 \1
교체하세요 . \1
두 번째 시퀀스의 시작부터 다음 시퀀스 발생까지 각 일치 항목(즉, 쉼표가 일치할 때마다)은 (
sed
빈 문자열로 대체됩니다.\1
한 줄에 그러한 시퀀스가 많이 있다고 가정하고 쉼표가 (
)
구분 기호 내에만 나타난다고 가정하면 sed
각 시퀀스에 대해 따옴표가 번갈아 표시됩니다. 다음은 여러 번 사용한 예입니다.
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
,\([^,)]*\)
- 유일한 참고 사항아니요전체 정규식에 대한 선택적 일치는,
쉼표입니다. 표현식과 입력에서 다른 블록이 앞에 나오므로sed
적용할 수 있습니다. 그러나 다른 모든 항목이 동일하면 쉼표가 우선순위를 가집니다. 이는 s를 어디에나 삽입sed
하지 않는 유일한 이유입니다.''
다른 두 개는 블록의 각 바이트 사이에서 수행됩니다.아니요sed
- 구분이 적용된 경우 빈 문자열과 일치합니다.sed
not 및 not 의 모든 문자 시퀀스를 계속해서 일치시키고\2
저장합니다 . 이는 발생한 모든 쉼표를 대체합니다 . 채울 수 있는 지점에 도달할 때까지 이러한 방식으로 계속되며 그렇게 됩니다.)
,
,'\2'
(
\1
답변3
이 시도:
sed 's/,,/,\x27\x27,/'
\x27
16진수 이스케이프 코드입니다.'
데모
$ echo 'INSERT INTO `radcheck`(`id`, `username`, `attribute`, `op`, `value`) VALUES (,,00:23:32:c2:a9:e8,Auth-Type,:=,Accept);' |
> sed 's/,,/,\x27\x27,/'
INSERT INTO `radcheck`(`id`, `username`, `attribute`, `op`, `value`) VALUES (,'',00:23:32:c2:a9:e8,Auth-Type,:=,Accept);