programing

sed가 \t를 탭으로 인식하지 못하는 이유는 무엇입니까?

instargram 2023. 5. 12. 20:13
반응형

sed가 \t를 탭으로 인식하지 못하는 이유는 무엇입니까?

sed "s/\(.*\)/\t\1/" $filename > $sedTmpFile && mv $sedTmpFile $filename

나는 이것을 기대하고 있습니다.sed삽입 스크립트tab의 모든 행 앞에$filename하지만 그렇지 않습니다.어떤 이유로 그것은 삽입하고 있습니다.t대신.

의 일부 버전은 아닙니다.sed이해하다\t대신 리터럴 탭을 삽입하면 됩니다( - 그런 다음 V를 누릅니다).

Bash를 사용하면 다음과 같이 프로그래밍 방식으로 TAB 문자를 삽입할 수 있습니다.

TAB=$'\t' 
echo 'line' | sed "s/.*/${TAB}&/g" 
echo 'line' | sed 's/.*/'"${TAB}"'&/g'   # use of Bash string concatenation

@sedit는 올바른 경로에 있었지만 변수를 정의하는 것은 약간 어색합니다.

솔루션(배시별)

bash에서 이를 수행하는 방법은 따옴표로 묶은 단일 문자열 앞에 달러 기호를 넣는 것입니다.

$ echo -e '1\n2\n3'
1
2
3

$ echo -e '1\n2\n3' | sed 's/.*/\t&/g'
t1
t2
t3

$ echo -e '1\n2\n3' | sed $'s/.*/\t&/g'
    1
    2
    3

문자열에 변수 확장이 포함되어야 하는 경우 따옴표로 묶은 문자열을 다음과 같이 함께 넣을 수 있습니다.

$ timestamp=$(date +%s)
$ echo -e '1\n2\n3' | sed "s/.*/$timestamp"$'\t&/g'
1491237958  1
1491237958  2
1491237958  3

설명.

인바시$'string'"ANSI-C 확장"을 발생시킵니다.그리고 그것이 우리 대부분이 사용할 때 기대하는 것입니다.\t,\r,\n기타 출처: https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-Quoting

$'string' 형식의 단어는 특수하게 처리됩니다.단어가 문자열로 확장되고 백슬래시 이스케이프 문자가 ANSIC 표준에 지정된 대로 대체됩니다.백슬래시 이스케이프 시퀀스가 있으면 디코딩됩니다.

확장된 결과는 달러 기호가 없었던 것처럼 단일 인용으로 표시됩니다.

솔루션(배시를 방지해야 하는 경우)

저는 개인적으로 바시즘을 피한다고 해서 코드가 이식되지는 않기 때문에 바시즘을 피하려는 대부분의 노력은 어리석은 것이라고 생각합니다.(만약 당신이 그것을 shebang하면 당신의 코드는 덜 부서질 것입니다.bash -eu당신이 bash를 피하고 사용하려고 노력하는 경우보다.sh[당신이 절대적인 POSIX 닌자가 아니라면요.]하지만 그것에 대해 종교적인 논쟁을 하기보다는, 저는 당신에게 최고의* 대답을 할 것입니다.

$ echo -e '1\n2\n3' | sed "s/.*/$(printf '\t')&/g"
    1
    2
    3

최고의 답?네, 대부분의 안티배시 셸 스크립터가 코드에서 잘못하는 한 가지 예는 사용하기 때문입니다.echo '\t'@robrecord의 대답처럼.그것은 GNU 에코에서는 작동하지만 BSD 에코에서는 작동하지 않습니다.그것은 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 의 The Open Group에 의해 설명됩니다. 그리고 이것은 왜 바시즘을 피하려고 시도하는 것이 보통 실패하는지에 대한 예입니다.

Ubuntu 12.04(LTS)에서 Bash 셸과 함께 다음과 같은 기능을 사용했습니다.

탭이 있는 새 줄을 추가하려면 처음 일치할 때 번째 줄을 추가합니다.

sed -i '/first/a \\t second' filename

첫 번째를으로, 번째로 바꾸려면:

sed -i 's/first/\\t second/g' filename

사용하다$(echo '\t')패턴 주위에 따옴표가 필요합니다.

예: 탭을 제거하는 방법

sed "s/$(echo '\t')//"

당신은 필요없다니습가할을 사용할 필요가 sed실제로 줄 앞에 탭을 삽입하려는 경우 대체 작업을 수행합니다.이 경우를 대체하는 것은 특히 대용량 파일을 사용하는 경우 인쇄하는 것에 비해 비용이 많이 드는 작업입니다.정규식이 아니기 때문에 읽기도 더 쉽습니다.

예를 들어 어색함

awk '{print "\t"$0}' $filename > temp && mv temp $filename

Mac에서 사용했습니다.

sed -i '' $'$i\\\n\\\thello\n' filename

참조용으로 이 링크 사용

sed하지 \t다른 탈출 시퀀스도 마찬가지입니다.\n그 점에 관해서는내가 찾은 유일한 방법은 스크립트에 탭 문자를 실제로 삽입하는 것이었습니다.sed.

즉, Perl 또는 Python 사용을 고려해 보는 것이 좋습니다.다음은 모든 스트림 정규화에 사용하는 짧은 Python 스크립트입니다.

#!/usr/bin/env python
import sys
import re

def main(args):
  if len(args) < 2:
    print >> sys.stderr, 'Usage: <search-pattern> <replace-expr>'
    raise SystemExit

  p = re.compile(args[0], re.MULTILINE | re.DOTALL)
  s = sys.stdin.read()
  print p.sub(args[1], s),

if __name__ == '__main__':
  main(sys.argv[1:])

BSD sed 대신 perl을 사용합니다.

ct@MBA45:~$ python -c "print('\t\t\thi')" |perl -0777pe "s/\t/ /g"
   hi

다른 도 이것을 했다고 생각합니다.sed,AWK등).하지만, 나의bash-특정 답변(macOS High Sierra 및 CentOS 6/7에서 테스트됨)은 다음과 같습니다.

제안했던 한 검색 및 를 사용하는 것을 합니다.perl이를 위해, 다음과 같이.참고: 정규식에 대한 괄호 앞에 백슬래시를 둘 필요가 없으며, 이 코드 행은 다음과 같은 방법을 반영합니다.$1보다 사용하기에 더 좋습니다.\1와 함께perl대체 연산자(예: Perl 5 설명서당).

perl -pe 's/(.*)/\t$1/' $filename > $sedTmpFile && mv $sedTmpFile $filename

그러나 ghostdog74에서 지적한 바와 같이 실제로 원하는 작업은 tmp 파일을 입력/대상 파일로 변경하기 전에 각 줄의 시작 부분에 탭을 추가하는 것이기 때문에 ($filename), , , , 를perl다음과 같은 수정 사항이 있습니다.

perl -pe 's/^/\t/' $filename > $sedTmpFile && mv $sedTmpFile $filename
## OR
perl -pe $'s/^/\t/' $filename > $sedTmpFile && mv $sedTmpFile $filename

물론 tmp 파일은 불필요하므로 모든 것을 '제자리에서' 하는 것이 좋습니다(추가).-iflag를 사용하여 .

perl -i -pe $'s/^/\t/' $filename
TAB=$(printf '\t')
sed "s/${TAB}//g" input_file

입력 파일에서 탭을 제거하는 Red Hat에서 작동합니다.

특정 문자가 사용되지 않는 경우 "\t"를 다른 문자로 변환할 수 있습니다.cat my_file | tr "\t", | sed "s/(*.)/,\1/"

언급URL : https://stackoverflow.com/questions/2610115/why-is-sed-not-recognizing-t-as-a-tab

반응형