최근 유용한 Perl one-liner(또는 Perl과 관련된 파이프)는 무엇입니까?[닫은]

StackOverflow https://stackoverflow.com/questions/111868

  •  02-07-2019
  •  | 
  •  

문제

단일 라이너는 다음을 수행해야 합니다.

  • 실제 문제를 해결하다
  • 광범위하게 비밀스럽지 않아야 함(이해하고 재현하기 쉬워야 함)
  • 작성하는 데 시간을 투자할 가치가 있어야 합니다(너무 영리해서는 안 됨).

실용적인 팁과 요령(보완적인 예)을 찾고 있습니다. perldoc perlrun).

도움이 되었습니까?

해결책 6

한 곳에서 수집된 답변의 모든 한 줄 내용:

  • perl -pe's/([\d.]+)/localtime $1/e;' access.log

  • ack $(ls t/lib/TestPM/|awk -F'.' '{print $1}'|xargs perl -e 'print join "|" => @ARGV') aggtests/ t -l

  • perl -e'while(<*.avi>) { s/avi$/srt/; rename <*.srt>, $_ }'

  • find . -name '*.whatever' | perl -lne unlink

  • tail -F /var/log/squid/access.log | perl -ane 'BEGIN{$|++} $F[6] =~ m{\Qrad.live.com/ADSAdClient31.dll} && printf "%02d:%02d:%02d %15s %9d\n", sub{reverse @_[0..2]}->(localtime $F[0]), @F[2,4]'

  • export PATH=$(perl -F: -ane'print join q/:/, grep { !$c{$_}++ } @F'<<<$PATH)

  • alias e2d="perl -le \"print scalar(localtime($ARGV[0]));\""

  • perl -ple '$_=eval'

  • perl -00 -ne 'print sort split /^/'

  • perl -pe'1while+s/\t/" "x(8-pos()%8)/e'

  • tail -f log | perl -ne '$s=time() unless $s; $n=time(); $d=$n-$s; if ($d>=2) { print qq ($. lines in last $d secs, rate ),$./$d,qq(\n); $. =0; $s=$n; }'

  • perl -MFile::Spec -e 'print join(qq(\n),File::Spec->path).qq(\n)'

설명은 해당 답변을 참조하세요.

다른 팁

내 슬라이드를 참조하세요. “Perl 명령줄 옵션에 대한 현장 가이드.”

여러분은 이것을 Perl이라고 생각하지 않을 수도 있지만 저는 Perl을 사용합니다. 확인 종교적으로(Perl로 작성된 스마트 grep 대체임) 예를 들어 API의 특정 부분에 액세스하는 모든 Perl 테스트를 편집할 수 있습니다.

vim $(ack --perl -l 'api/v1/episode' t)

참고로 vim을 사용하면 다음을 수행할 수 있습니다. 편집기의 버퍼에서 모든 테스트를 실행하세요..

좀 더 명확한(간단하다면) Perl을 사용하려면 t/lib/TestPM 디렉토리에 있는 테스트 픽스처를 얼마나 많은 테스트 프로그램에서 사용했는지 알아야 했습니다(명확성을 위해 명령을 줄였습니다).

ack $(ls t/lib/TestPM/|awk -F'.' '{print $1}'|xargs perl -e 'print join "|" => @ARGV') aggtests/ t -l

"조인"이 결과를 정규식으로 변환하여 ack에 제공하는 방법에 유의하세요.

문제:미디어 플레이어는 해당 비디오 파일과 이름이 다르기 때문에 자막을 자동으로 로드하지 않습니다.

해결책:*.avi(비디오가 있는 파일)와 일치하도록 모든 *.srt(자막이 있는 파일)의 이름을 바꿉니다.

perl -e'while(<*.avi>) { s/avi$/srt/; rename <*.srt>, $_ }'

경고:원본 영상과 자막 파일 이름의 정렬 순서는 동일해야 합니다.

위의 한 줄짜리 코드에 대한 좀 더 자세한 버전은 다음과 같습니다.

my @avi = glob('*.avi');
my @srt = glob('*.srt');

for my $i (0..$#avi)
{
  my $video_filename = $avi[$i];
  $video_filename =~ s/avi$/srt/;   # 'movie1.avi' -> 'movie1.srt'

  my $subtitle_filename = $srt[$i]; # 'film1.srt'
  rename($subtitle_filename, $video_filename); # 'film1.srt' -> 'movie1.srt'
}

오징어 로그 파일.정말 대단하지 않나요?기본적으로는 시간 필드로 에포크로부터의 초를 갖습니다.다음은 오징어 로그 파일을 읽고 시간을 사람이 읽을 수 있는 날짜로 변환하는 한 줄짜리 코드입니다.

perl -pe's/([\d.]+)/localtime $1/e;' access.log

약간만 조정하면 관심 있는 키워드가 포함된 줄만 표시되도록 할 수 있습니다.다음 stackoverflow.com 시계는 사람이 읽을 수 있는 날짜가 포함된 해당 행만 액세스하고 인쇄합니다.더 유용하게 만들기 위해 다음과 같은 출력을 제공하고 있습니다. tail -f, 실시간으로 액세스를 볼 수 있습니다.

tail -f access.log | perl -ne's/([\d.]+)/localtime $1/e,print if /stackoverflow\.com/'

사용의 일반적인 관용어 find ... -exec rm {} \; 디렉토리 트리 어딘가에서 파일 세트를 삭제하는 것은 다음을 실행한다는 점에서 특별히 효율적이지 않습니다. rm 발견된 각 파일에 대해 한 번씩 명령을 실행합니다.컴퓨터가 그다지 빠르지 않았던 시절부터 태어난 내 습관 중 하나는(아주!) 많은 호출을 컴퓨터로 대체하는 것입니다. rm Perl을 한 번만 호출하면:

find . -name '*.whatever' | perl -lne unlink

그만큼 perl 명령줄의 일부는 다음에 의해 방출된* 파일 목록을 읽습니다. find, 한 줄에 하나씩, 개행 문자를 잘라내고 Perl의 내장 기능을 사용하여 파일을 삭제합니다. unlink() 함수는 $_ 명시적인 인수가 제공되지 않은 경우 인수로 사용됩니다.($_ 덕분에 각 입력 라인에 설정됩니다. -n 플래그.) (*요즘 대부분의 find 명령은 -print 기본적으로 해당 부분은 생략해도 됩니다.)

나는 이 관용구를 좋아하는 이유는 효율성 때문일 뿐만 아니라(요즘 덜 중요할 수도 있지만) 전통적인 키를 입력하는 것보다 코드가 적고 어색한 키가 적기 때문입니다. -exec rm {} \; 순서.또한 공백, 따옴표 등이 포함된 파일 이름으로 인해 발생하는 인용 문제를 방지합니다.(더 강력한 버전에서는 다음을 사용할 수 있습니다. find'에스 -print0 선택하고 물어보세요 perl 줄 대신 널로 구분된 레코드를 읽으려고 하지만 일반적으로 내 파일 이름에 개행 문자가 포함되어 있지 않다고 확신합니다.)

내가 가장 많이 사용하는 Perl 원라이너는 Perl 계산기입니다.

perl -ple '$_=eval'

$work에서 가장 큰 대역폭을 차지하는 것 중 하나는 다운로드 웹 광고입니다. 그래서 저는 수확을 기다리고 있는 낮게 매달린 과일을 보고 있습니다.Google 광고를 없앴고 이제는 Microsoft가 눈에 띕니다.그래서 로그 파일에 대해 tail을 실행하고 관심 있는 줄을 선택합니다.

tail -F /var/log/squid/access.log | \
perl -ane 'BEGIN{$|++} $F[6] =~ m{\Qrad.live.com/ADSAdClient31.dll}
    && printf "%02d:%02d:%02d %15s %9d\n",
        sub{reverse @_[0..2]}->(localtime $F[0]), @F[2,4]'

Perl 파이프가 하는 일은 autoflush를 true로 설정하여 시작하여 실행되는 모든 내용이 즉시 인쇄되도록 하는 것입니다.그렇지 않으면 출력이 청크되어 출력 버퍼가 채워질 때 일괄 처리 라인을 수신합니다.-a 스위치는 각 입력 행을 공백으로 분할하고 결과를 @F 배열에 저장합니다(입력 레코드를 $1, $2, $3...으로 분할하는 awk의 기능에서 영감을 받은 기능).변수).

줄의 7번째 필드에 우리가 찾는 URI가 포함되어 있는지 확인합니다(흥미롭지 않은 메타 문자를 탈출하는 수고를 덜기 위해 \Q를 사용함).일치하는 항목이 발견되면 시간, 소스 IP 및 원격 사이트에서 반환된 바이트 수를 보기 좋게 인쇄합니다.

시간은 첫 번째 필드에서 에포크 시간을 취하고 'localtime'을 사용하여 해당 구성요소(시, 분, 초, 일, 월, 연도)로 분해하여 얻습니다.처음 세 요소 반환(초, 분, 시간)의 조각을 취하고 순서를 반대로 바꾸어 시간, 분, 초를 가져옵니다.이는 원래 @F 배열의 세 번째(IP 주소) 및 다섯 번째(크기) 조각과 함께 3개 요소 배열로 반환됩니다.이 5개의 인수는 결과 형식을 지정하는 sprintf에 전달됩니다.

@dr_pepper

제거하다 오자 중복됨 $PATH:

$ export PATH=$(perl -F: -ane'print join q/:/, grep { !$c{$_}++ } @F'<<<$PATH)

다음에서 고유한 깨끗한 경로를 인쇄합니다. %PATH% 환경 변수(건드리지 않습니다. ../ 마찬가지로 교체 File::Spec->rel2abs ~에 의해 Cwd::realpath 그것이 바람직한 경우) 더 이식성이 뛰어난 것은 한 줄이 아닙니다.

#!/usr/bin/perl -w
use File::Spec; 

$, = "\n"; 
print grep { !$count{$_}++ } 
      map  { File::Spec->rel2abs($_) } 
      File::Spec->path;

Ovids vim/ack 조합에 대한 응답:

나 역시 종종 무언가를 검색한 다음 Vim에서 일치하는 파일을 열고 싶어서 얼마 전에 약간의 바로가기를 만들었습니다(ZSH에서만 작동하는 것 같습니다).

function vimify-eval; {
    if [[ ! -z "$BUFFER" ]]; then
        if [[ $BUFFER = 'ack'* ]]; then
            BUFFER="$BUFFER -l"
        fi  
        BUFFER="vim  \$($BUFFER)"
        zle accept-line
    fi  
}

zle -N vim-eval-widget vimify-eval

bindkey '^P' vim-eval-widget

다음과 같이 작동합니다:나는 ack를 사용하여 무언가를 검색합니다. ack some-pattern.결과를 보고 마음에 들면 위쪽 화살표를 눌러 확인 라인을 다시 가져온 다음 Ctrl+P를 누릅니다.그러면 ZSH는 명령이 "ack"로 시작하는 경우에만 파일 이름을 나열하기 위해 "-l"을 추가합니다.그런 다음 명령 주위에 "$(...)"를 넣고 명령 앞에 "vim"을 넣습니다.그런 다음 모든 것이 실행됩니다.

나는 신기원 시간을 유용한 날짜 스탬프로 신속하게 변환하기 위해 이것을 자주 사용합니다.

perl -l -e 'print scalar(localtime($ARGV[0]))'

셸에서 별칭을 만듭니다.

alias e2d="perl -le \"print scalar(localtime($ARGV[0]));\""

그런 다음 에포크 번호를 별칭에 파이프합니다.

echo 1219174516 | e2d

Unix/Linux의 많은 프로그램과 유틸리티는 시간을 표현하기 위해 epoch 값을 사용하므로 이것이 나에게 매우 귀중한 것으로 판명되었습니다.

경로 변수에서 중복 항목을 제거합니다.

set path=(`echo $path | perl -e 'foreach(split(/ /,<>)){print $_," " unless $s{$_}++;}'`)

MS-DOS 줄 끝을 제거합니다.

perl -p -i -e 's/\r\n$/\n/' htdocs/*.asp

쉘 스크립팅 중에 읽을 수 있는 PATH 버전을 확인해야 하는 경우가 종종 있습니다.다음 단일 라이너는 모든 경로 항목을 자체 줄에 인쇄합니다.

시간이 지남에 따라 이 단일 라이너는 여러 단계를 거쳐 발전했습니다.

UNIX(버전 1):

perl -e 'print join("\n",split(":",$ENV{"PATH"}))."\n"'

Windows(버전 2):

perl -e "print join(qq(\n),split(';',$ENV{'PATH'})).qq(\n)"

UNIX/Windows 모두(@j-f-sebastian의 q/qq 팁 사용)(버전 3):

perl -MFile::Spec -e 'print join(qq(\n),File::Spec->path).qq(\n)' # UNIX
perl -MFile::Spec -e "print join(qq(\n),File::Spec->path).qq(\n)" # Windows

웹 페이지를 열지 않고도 스택 오버플로 평판 추출:

perl -nle "print '  Stack Overflow        ' . $1 . '  (no change)' if /\s{20,99}([0-9,]{3,6})<\/div>/;" "SO.html"  >> SOscores.txt

이는 사용자 페이지가 이미 SO.html 파일로 다운로드되었다고 가정합니다.저는 이 목적으로 wget을 사용합니다.여기의 표기법은 Windows 명령줄에 대한 것입니다.Linux나 Mac OS X에서는 약간 다릅니다.출력은 텍스트 파일에 추가됩니다.

저는 이를 BAT 스크립트에서 사용하여 계열 내 4개 사이트에 대한 평판 샘플링을 자동화했습니다.스택 오버플로, 서버 오류, 슈퍼 유저 및 메타 스택 오버플로.

내 ~/bin에 자리잡은 가장 최근의 한 줄짜리 문장 중 하나:

perl -ne '$s=time() unless $s; $n=time(); $d=$n-$s; if ($d>=2) { print "$. lines in last $d secs, rate ",$./$d,"\n"; $. =0; $s=$n; }'

로그 파일의 꼬리에 대해 이를 사용하면 출력되는 행의 속도를 인쇄합니다.

웹서버에서 초당 몇 번의 히트가 발생하는지 알고 싶으십니까?꼬리 -f 로그 | this_script.

사람이 읽을 수 있는 출력을 다음에서 가져옵니다. du, 크기별로 정렬:

perl -e '%h=map{/.\s/;7x(ord$&&10)+$`,$_}`du -h`;print@h{sort%h}'

흰색 공간 분리 된 스탠자 (이름/값 쌍 목록) 스트림을 필터링하여 각 스탠자를 개별적으로 정렬합니다.

perl -00 -ne 'print sort split /^/'

네트워크 관리자는 특히 Cisco ASDM 자동 제안을 사용하는 동안 "서브넷 주소"를 "호스트 주소"로 잘못 구성하는 경향이 있습니다.이 간단한 단일 라이너는 구성 파일에서 그러한 구성 오류를 검색합니다.

잘못된 사용법: permit host 10.1.1.0

올바른 사용법: permit 10.1.1.0 255.255.255.0

perl -ne "print if /host ([\w\-\.]+){3}\.0 /" *.conf

이는 Windows에서 테스트 및 사용되었습니다. 올바른 사용을 위해 어떤 방식으로든 수정해야 하는지 제안해 주세요.

모든 탭을 공백으로 확장합니다. perl -pe'1while+s/\t/" "x(8-pos()%8)/e'

물론, Vim에서 :set et, :ret를 사용하여 이 작업을 수행할 수 있습니다.

텍스트 부분을 식별하는 데 사용되는 태그 목록이 있습니다.마스터 목록의 형식은 다음과 같습니다.

text description {tag_label}

중요한 것은 {tag_label} 중복되지 않습니다.다음과 같은 멋진 간단한 스크립트가 있습니다.

perl -ne '($c) = $_ =~ /({.*?})/; print $c,"\n" ' $1 | sort  | uniq -c | sort -d

나는 쉘이나 펄에서 많은 것을 할 수 있다는 것을 알고 있지만 이것이 가장 먼저 떠오른 것입니다.

종종 표 형식의 데이터를 구성 파일로 변환해야 했습니다.예를 들어, 네트워크 케이블링 공급업체는 Excel 형식의 패치 기록을 제공하며 우리는 해당 정보를 사용하여 구성 파일을 생성해야 합니다.즉,

Interface, Connect to, Vlan
Gi1/0/1, Desktop, 1286
Gi1/0/2, IP Phone, 1317

다음과 같아야 합니다:

interface Gi1/0/1
 description Desktop
 switchport access vlan 1286

등등.동일한 작업은 테이블 형식 데이터 앞에 필드 이름을 추가하고 평면 구조로 바꿔야 하는 다양한 관리 작업에서 여러 형태로 다시 나타납니다.나는 일부 DBA가 Excel 시트에서 SQL 문을 준비하는 데 많은 시간을 낭비하는 것을 보았습니다.이 간단한 단일 라이너를 사용하여 달성할 수 있습니다.즐겨 사용하는 스프레드시트 도구를 사용하여 표 형식 데이터를 CSV 형식으로 저장하고 이 한 줄짜리 실행을 실행하세요.머리글 행의 필드 이름은 개별 셀 값 앞에 추가되므로 요구 사항에 맞게 편집해야 할 수도 있습니다.

perl -F, -lane "if ($.==1) {@keys = @F} else{print @keys[$_].$F[$_] foreach(0..$#F)} " 

주의할 점은 필드 이름이나 값에 쉼표가 포함되어서는 안 된다는 것입니다.아마도 이러한 예외를 한 줄로 잡기 위해 더 자세히 설명할 수 있을 것입니다. 가능하다면 이를 개선해 주십시오.

다음은 컬렉션 압축 로그 파일을 처리할 때 유용하다고 생각하는 것입니다.

   open STATFILE, "zcat $logFile|" or die "Can't open zcat of $logFile" ;

언젠가 나는 'perl -e'를 사용하여 명령줄에서 수행할 수 있을 만큼 짧은 Perl로 수행하고 싶은 모든 작업을 인용하는 번거로움 없이 일반적인 ZSH 기능을 사용하여 더 좋고, 쉽고, 빠르게 수행할 수 있다는 것을 발견했습니다.예:위의 예는 다음과 같이 수행할 수 있습니다.

for foo in *.avi; mv *.srt ${foo:r}.srt

업데이트

위의 온라인 사용자는 명백히 틀렸습니다. 주의 깊게 읽지 않아서 죄송합니다.올바른 버전은 다음과 같습니다.

srt=(*.srt); for foo in *.avi; mv $srt[1] ${foo:r}.srt && srt=($srt[2,-1])
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top