증분 변수를 사용하여 페이지 링크 생성

증분 변수를 사용하여 페이지 링크 생성

링크를 고려하다

https://unix.stackexchange.com/questions/tagged/linux?page=2&sort=newest&pagesize=15 https://unix.stackexchange.com/questions/tagged/linux?page=3&sort=newest&pagesize=15 https://unix.stackexchange.com/questions/tagged/linux?page=4&sort=newest&pagesize=15

여기서 '페이지'가 증가합니다. 페이지가 115개인 경우 마지막 페이지의 페이지 값은 115가 됩니다.

2개의 예제 링크를 처리하여 링크의 어느 부분이 증가하는지 어떻게 알 수 있나요?

쉘 스크립트를 사용하여 115개의 링크를 모두 생성해야 합니다.

입력은 2페이지와 3페이지에 대한 2개의 링크와 총 페이지 수입니다.

저는 bash 쉘을 사용하는데, Python도 사용할 수 있습니다.

답변1

^이것은 Perl의 비트 배타적 OR(XOR) 연산자( ) 를 사용하는 방법을 보여주기 위한 Perl 스크립트입니다 .

스크립트

나는 그것을 부른다 cmp.pl.

#!/usr/bin/perl -w

use strict;
use warnings;
# $s1 = "http://unix.stackexchange.com/questions/tagged/linux?page=2&sort=newest&pagesize=15";
# $s2 = "http://unix.stackexchange.com/questions/tagged/linux?page=3&sort=newest&pagesize=15";
# $np = 115

my $s1 = $ARGV[0];
my $s2 = $ARGV[1];
my $np = $ARGV[2];

my $posOfDiff;

my $mask = $s1 ^ $s2;
while ($mask =~ /[^\0]/g) {
  $posOfDiff = $-[0];
}


for (my $idx = 1; $idx <= $np; $idx++) {
  my $newStr = $s1;
  substr($newStr,$posOfDiff,1) = $idx;
  print "$newStr\n";
}

세부 사항

^이 스크립트의 독특한 점은 Perl의 ( ) 연산자를 사용한다는 것입니다 . 이 접근 방식의 힘은 다음 코드에 있습니다.

my $mask = $s1 ^ $s2;
while ($mask =~ /[^\0]/g) {
  $posOfDiff = $-[0];
}

위의 내용은 $mask2개의 문자열을 사용하여 마스크( )를 생성합니다. XOR 마스크는 $s1사이에 일치하는 값이 0을 포함 $s2하고 고유 값이 1을 포함하는 벡터입니다 . 이를 확신하고 싶다면 다음 코드 줄을 추가할 수 있습니다.

my $mask = $s1 ^ $s2;
printf "[$_] is 0x%02x\n", ord($_) for split //, $mask;

페이셜 마스크 용기

그러면 printf다음과 같은 출력이 생성됩니다.노트:이러한 문자는 인쇄할 수 없으며 16진수 값입니다. 0x00은 널 문자의 16진수 값이고, 0x01은 1입니다.

...
[] is 0x00
[] is 0x00
[] is 0x00
[] is 0x00
[] is 0x00
[ ] is 0x01
[] is 0x00
[] is 0x00
...

0이 아닌 값이 다른 값을 나타낼 때 반환되는 값입니다. 다른 예:

$ perl -we '$a="ab"; $b="ac"; $c=$a ^ $b; printf "[$_] is 0x%02x\n", ord($_) for split //, $c;'
[] is 0x00
[] is 0x01

$ perl -we '$a="ab"; $b="ad"; $c=$a ^ $b; printf "[$_] is 0x%02x\n", ord($_) for split //, $c;'
[] is 0x00
[] is 0x06

$ perl -we '$a="ab"; $b="ae"; $c=$a ^ $b; printf "[$_] is 0x%02x\n", ord($_) for split //, $c;'
[] is 0x00
[] is 0x07

마스크를 통한 루프

루프의 또 다른 흥미로운 특징은 whilenull( )이 아닌 문자에 대해서만 루프를 돌린다는 것입니다. 따라서 귀하의 예에서는 실제로 while 루프를 1회만 실행합니다. 왜냐하면 2개의 문자열 사이에는 1개의 차이만 있기 때문입니다. 차이가 2개인 경우 2번 실행됩니다. 그래서 이것은 매우 효과적인 방법입니다.$mask\0

좀 더 설득력이 필요한 경우 추가 코드 줄을 추가하여 while루프 실행을 표시할 수 있습니다.

while ($mask =~ /[^\0]/g) {
  print "in the loop\n";
  print "what we're looking for:" . $-[0] . "\n";

다음 줄은 한 번만 표시됩니다.

in the loop
what we're looking for:58

차이점을 저장할 위치

일치하는 항목이 발견되면 while 루프의 본문이 실행되고 위치가 변수에 기록됩니다 $posOfDiff. 어떻게? 여기서의 장점은 $-[0] 변수를 사용한다는 것입니다. 이는 마지막으로 성공한 일치의 오프셋을 제공합니다.

$-[0]은 마지막으로 성공한 일치 시작 부분의 오프셋입니다.

이 일치는 루프의 제어 부분에서 발생하며 null 문자( )가 아닌 문자를 while찾고 있으므로 차이점 문자는 다음과 같습니다.$mask\0

$mask =~ /[^\0]/g

노트:꼬리는 gPerl의 일치 함수에게 이 작업을 전역적으로 수행하도록 지시하므로 문자열이 소진될 때까지 일치하는 항목을 계속 찾습니다 $mask.

또 뭐야?

스크립트의 나머지 부분은 거의 상용구 Perl이므로 더 이상 논의할 가치가 없습니다.

인용하다

답변2

Python에서는 다음을 사용할 수 있습니다.SequenceMatcher~에서difflib:

#!/usr/bin/env python
import difflib

url1 = "http://unix.stackexchange.com/questions/tagged/linux?page=2&sort=newest&pagesize=15"
url2 = "http://unix.stackexchange.com/questions/tagged/linux?page=3&sort=newest&pagesize=15"

matcher = difflib.SequenceMatcher(a=url1, b=url2)
matches = matcher.get_matching_blocks()

prefix = url1[:matches[0][2]]
suffix = url2[matches[1][1]:]

for i in range(2, 116):
    print prefix + str(i) + suffix

SequenceMatcher.get_matching_blocks()는 형식의 트리플 목록을 반환합니다 . (i, j, n)여기서 a[i:i+n] == b[j:j+n]처음 두 개의 트리플을 사용하여 페이지 번호 주위에 URL의 접두사와 접미사를 만들고 URL 범위를 반복합니다.

답변3

링크에 대한 다른 정보는 전혀 모르고, 페이지 번호만 변경된다고 가정한 저의 접근 방식입니다. 처음에는 생각했지만 시작점으로는 쓸모가 없는 diff -e전체 줄 교체 스크립트를 생성하는 것으로 나타났습니다 .ed

순수한 bash 솔루션은 다음과 같습니다.

#!/bin/bash
url1=${1:-"http://unix.stackexchange.com/questions/tagged/linux?page=2&sort=newest&pagesize=15"} 
url2=${2:-"http://unix.stackexchange.com/questions/tagged/linux?page=34&sort=newest&pagesize=15"}
pagenum=${3:-42}

function splitOnDigit() {
  prefix="${1%%[0-9]*}"
  url1="${1#$prefix}" # remainder if you strip the prefix
  url2="${2#$prefix}"
  suffix1="&${1#*&}" # remainder after the number
  suffix2="&${2#*&}"
  num="${url1%$suffix1}" # the number that we just split around
  if [[ $suffix1 == $1 ]]; then
    # if substitutions failed, we're at the end
    echo "$prefix$3"
    return
  fi

  if [[ $suffix1 == $suffix2 ]]; then
    echo "$prefix$3$suffix1"
  else
    echo -n "$prefix$num"
    splitOnDigit "$suffix1" "$suffix2" "$3"
  fi
}

splitOnDigit "$url1" "$url2" "$pagenum"

숫자를 구분하여 두 문자열을 비교합니다. 어딘가에 저장하고 실행하면 됩니다. 자체 포함되어 있습니다. 숫자의 변경된 부분이 예제에서처럼 발견된 첫 번째 부분이 아닌 경우 재귀 부분이 존재합니다.

전체 범위의 페이지 번호를 생성하려면 전체 프로세스를 루프에 넣습니다(구현하는 함수와 마찬가지로 url1 url2 pagenumber의 세 가지 매개변수 사용). 있는 그대로 작동할 만큼 빠르지만 문자열 수정은 한 번만 수행되고 반복된 숫자를 입력하는 접두사-접미사 쌍으로 저장됩니다.

관련 정보