
일부 열에 선행 작은따옴표가 포함된 입력 파일을 제어할 수 없는 수준으로 받았습니다.
'foo|'012|that's nice|bar
예상되는 출력을 얻으려면 각 필드에서 모든 선행 작은따옴표를 제거하고 싶습니다.
foo|012|that's nice|bar
awk를 사용하여 gsub 정규식 메타 문자가 ^
열별로 작동할 것이라고 가정했지만 줄 시작 부분에서만 작동하는 것 같습니다.
$ echo "'foo|'012|that's nice|bar" | awk -F'|' '{gsub(/^'\''/,"")}1'
foo|'012|that's nice|bar
각 열에서 선행 작은따옴표를 제거하는 방법은 무엇입니까?
답변1
아니요 awk
, sed
다음과 같이 할 수 있습니다.
sed -E "s/(^|\|)'/\1/g"
-E
확장 정규식으로 전환하는 옵션은 POSIX 표준의 다음 버전에 나타날 예정이지만 대부분의 구현에서는 이미 이를 지원합니다 sed
. 또는 and perl
대신 which를 사용할 수 있습니다 .sed
awk
perl -pe 's/(^|\|)'\''/$1/g'
또는:
perl -pe "s/(^|\|)\K'//g"
( 경기 시작을 \K
표시합니다 ).K
또는:
perl -pe "s/(?<![^|])'//g"
( '
앞에 문자가 없으면 대체 가능합니다 |
.)
또는 해당 awk
패턴을 사용하십시오.
perl -F'\|' -pe 's/^'\''// for @F; $_ = join "|", @F'
를 사용하려면 awk -F'|'
위의 perl
패턴 과 같이 각 필드에 대체를 적용해야 합니다 awk
.
awk -F'|' -v OFS='|' '
{
for (i = 1; i <= NF; i++) sub(/^'\''/, "", $ i)
print
}'
의 awk
경우 특수한 경우로 필드 구분 기호가 단일 문자인 경우 정규 표현식으로 처리되지 않으므로 이스케이프할 필요가 없습니다 |
.
$
in은 awk
숫자를 취하는 단항 연산자입니다. 1과 사이의 숫자이면 해당 필드를 반환합니다 NF
. 숫자가 0이면 전체 레코드를 반환하고, 그렇지 않으면 빈 문자열을 반환합니다.
sub()
그리고 gsub()
2개 또는 3개의 인수를 취할 수 있으며, 세 번째 인수((유일한) 대체 주제)가 제공되지 않으면 기본값은 전체 레코드( $0
)입니다. 다른 방법과 마찬가지로 다른 방법도 마찬가지입니다 gsub()
. 패턴의 모든 발생이 아니라 첫 번째 패턴 발생만 대체됩니다.sub()
s/x/y/g
s/x/y/
sed
sub()
gsub()
여기 정규식은 처음에 고정되어 있으므로 한 번만 일치할 수 있으므로 및 는 sub()
아무런 gsub()
효과가 없습니다.
IOW는 gsub()
각 필드에서 하나의 교체를 수행하는 대신 다음을 수행합니다.하나기본적으로 분할되지 않은 전체 레코드인 문자열입니다.
¹ 기술적으로는 다음과 같이 간주됩니다.숫자 문자열. 즉, 숫자처럼 보이면 그렇지 않으면 숫자로 처리됩니다. 빈 문자열은 문자열로 처리됩니다.
답변2
필드를 반복하고 각 필드의 따옴표 문자를 바꿔야 합니다. Stéphane이 사용 방법을 보여줍니다.awk
그들의 대답에.
$ mlr --csv --fs pipe -N put 'for (k,v in $*) { $[k] = sub(v, "^\047", "") }' file
foo|012|that's nice|bar
이는 다음을 사용합니다.밀러( mlr
)입력을 헤더 없는 CSV 데이터 세트로 읽습니다(파이프를 필드 구분 기호로 사용). 각 레코드에 대해 put
표현식은 모든 필드를 반복하고 작은따옴표(8진수에서는 047)인 경우 첫 번째 문자를 제거합니다.
Miller의 다른 접근 방식은 apply()
필드에서 초기 작은따옴표를 제거하는 함수를 적용하는 것입니다. 이 기능은 모든 레코드의 모든 필드에 적용됩니다.
$ mlr --csv --fs pipe -N put '$* = apply($*, func(k,v) { return { k: sub(v, "^\047", "") } })' file
foo|012|that's nice|bar
답변3
GNU awk 사용 gensub()
(다른 awk도 지원하지만 아직 POSIX에서는 필요하지 않음):
$ awk '{$0=gensub(/(^|\|)\047/,"\\1","g")} 1' file
foo|012|that's nice|bar
위에서 할 수 있어 print gensub(...)
좀 더 효율적이지만 할당 $0
하고 인쇄하고 있습니다.1
아래의 다른 답변과 일관성을 유지하고 교체 후 실제로 필드에서 작업을 수행해야 하는 경우를 대비합니다.
또는 GNU awk를 사용하세요 RT
.
$ awk -v RS='|' '{ORS=RT; sub(/^\047/,"")} 1' file
foo|012|that's nice|bar
또는 awk를 사용하십시오.
$ awk '{gsub(/\|\047/,"|"); sub(/^\047/,"")} 1' file
foo|012|that's nice|bar
또는 awk를 사용하십시오.
$ awk -F "[|]'" -v OFS='|' '{$1=$1; sub(/^\047/,"")} 1' file
foo|012|that's nice|bar
바라보다http://awk.freeshell.org/PrintASingleQuote나는 왜 를 대표하는 \047
데 익숙합니까 '
?
알로크문자열 조작 함수( *sub()
, match()
, *split()
, index()
, 등) substr()
은 length()
매개변수로 제공하는 모든 문자열에서 작동합니다. 문자열 매개변수가 필요하지 않은 문자열의 경우 기본값은 $0
매개변수로 제공되는 문자열이 없다는 것입니다. 문자열을 작업하기 전에 필드 등으로 분할하지 않으므로 어떤 이유로 한 번에 하나의 필드를 변경하려면 sub()
한 번에 각 필드를 호출하는 루프를 작성해야 합니다.
$ awk 'BEGIN{FS=OFS="|"} {for (i=1; i<=NF; i++) sub(/^\047/,"",$i)} 1' file
foo|012|that's nice|bar
그러나 이는 다음 중 하나를 사용하는 것보다 효율성이 떨어집니다.
awk '{$0=gensub(/(^|\|)\047/,"\\1","g")} 1' file
awk '{gsub(/\|\047/,"|"); sub(/^\047/,"")} 1' file
부터:
*sub()
NF를 1~2번이 아니라 행당 여러 번 호출합니다 .- 이는 awk가 필드 분할을 수행하도록 하는 필드를 나타내며
$i
, 위의 다음 2개 스크립트와 같이 스크립트에서 해당 필드를 참조하지 않으면 대부분의 awk는 각 레코드를 필드로 분할하는 데 시간이 걸리지 않습니다. $0
필드를 변경하기 위해 호출될 때마다sub()
awk가 필드에서 다시 빌드되도록 강제합니다 (즉, 행당 최대 NF 번).
답변4
사용행복하다(이전 Perl_6)
<(…)>
캡처 태그 사용 :
~$ raku -pe "s:g/ [ ^ | \| ] <( \' )> //;" file
#OR
~$ raku -pe 's:g/ [ ^ | \| ] <( \c[APOSTROPHE] )> //;' file
또는앞으로 되돌아보기를 사용하십시오 <?after … >
:
~$ raku -pe "s:g/ <?after ^ | \| > \' //;" file
#OR
~$ raku -pe 's:g/ <?after ^ | \| > \c[APOSTROPHE] //;' file
또는<!after … >
<-[…]>
부정적인 사용자 정의 문자 클래스 에 부정적인 뒤돌아보기를 사용하십시오.
~$ raku -pe "s:g/ <!after <-[|]> > \' //;" file
#OR
~$ raku -pe 's:g/ <!after <-[|]> > \c[APOSTROPHE] //;' file
또는사용 split
/ join
:
~$ raku -ne ".split(/ [ ^ | \| ] \'? /)[1..*].join('|').put" file
#OR
~$ raku -ne '.split(/ [ ^ | \| ] \c[APOSTROPHE]? /)[1..*].join("|").put' file
필요한 경우 위의 대괄호 그룹을 사용합니다(Raku의 대괄호는 를 잡지 않습니다 $0
등 $1
).
입력 예(빈 열에 대해서도 테스트):
'foo|'012|that's nice|bar||baz
출력 예(모든 예):
foo|012|that's nice|bar||baz
1 Perl 예제를 제공한 @StéphaneChazelas에게 감사드립니다.